2013-03-15 35 views
17

Trong dự án của tôi, tôi đang gặp sự cố khi thực hiện kiểm tra đơn vị. Một vấn đề là chỉ cần làm một bài kiểm tra tích hợp là nhanh hơn nhiều để viết và cũng kiểm tra các thành phần thực sự làm việc cùng nhau. Đơn vị thử nghiệm cuốn tiểu thuyết "thuật toán" hoặc như vậy có vẻ dễ dàng hơn nhiều. Các lớp dịch vụ kiểm thử đơn vị nó chỉ cảm thấy sai và vô dụng.Dữ liệu mùa xuân: Kiểm tra đơn vị lớp dịch vụ

Tôi đang sử dụng mockito để kho lưu trữ dữ liệu mùa xuân giả (và do đó truy cập DB). Vấn đề là nếu tôi nói với kho lưu trữ giả để trả về thực thể A trên phương thức gọi getById, nó rõ ràng sẽ trả về nó và dịch vụ cũng sẽ trả về nó. Vâng, dịch vụ thực hiện một số công cụ bổ sung, nhưng những thứ rất nhỏ, như tải bộ sưu tập lười biếng (từ ngủ đông). Rõ ràng tôi không có bất kỳ bộ sưu tập lười biếng (proxy) trong một bài kiểm tra đơn vị.

Ví dụ:

@Test 
public void testGetById() { 
    System.out.println("getById"); 
    TestCompound expResult = new TestCompound(id, "Test Compound", "9999-99-9", null, null, null); 

    TestCompoundRepository mockedRepository = mock(TestCompoundRepository.class); 
    when(mockedRepository.findOne(id)).thenReturn(expResult); 

    ReflectionTestUtils.setField(testCompoundService, "testCompoundRepository", 
      mockedRepository, TestCompoundRepository.class); 

    TestCompound result = testCompoundService.getById(id); 
    assertEquals(expResult, result); 
} 

hoan hô, phần còn lại thành công. Thật bất ngờ! Không thực sự không.

Một số người có thể giải thích cho tôi những gì tôi đang làm sai? Nếu không thì điểm của thử nghiệm đó là gì? Tôi có nghĩa là tôi nói để trả lại expResult và sau đó nó được trả lại. Wow. Thật bất ngờ! Có vẻ như tôi đang thử nghiệm nếu mockito hoạt động chứ không phải Dịch vụ của tôi.

EDIT:

Lợi ích duy nhất tôi xem một số đã lỗi ngớ ngẩn xảy ra như để lại một dòng không mong muốn đó mà bộ trở lại giá trị null hay cái gì tương tự như ngu ngốc. Các trường hợp như vậy sẽ bị bắt bởi phép thử đơn vị. Tuy nhiên, tỷ lệ "nỗ lực thưởng" có vẻ xấu?

+0

Quyền của bạn với chuyến tàu tư tưởng, hãy cho tôi biết nếu bạn có bất kỳ câu hỏi hoặc câu hỏi nào khác liên quan đến câu trả lời của tôi. –

+0

Nếu dịch vụ của bạn có các chức năng làm nhiều việc hơn là chỉ truy cập cơ sở dữ liệu, đó là những gì bạn nên kiểm tra. Một hoạt động CRUD đơn giản chỉ có ý nghĩa để kiểm tra ở lớp Tích hợp DB. Nếu phương thức dịch vụ 'findById' của bạn đang gọi phương thức' findById' cơ sở dữ liệu, sau đó tăng cường kết quả với một số thông tin không có trong cùng một DB/Bảng/Kho lưu trữ - ví dụ cho bản ghi người dùng có thể bao gồm tìm kiếm tra cứu ngược IP - sau đó điều đó có ý nghĩa để kiểm tra ở cấp dịch vụ. Nhưng chế nhạo * mọi thứ * chỉ đơn giản là kiểm tra thử nghiệm của bạn và khuôn khổ giả. –

Trả lời

8

Một trong những lý do tôi muốn kiểm tra kho dữ liệu Spring của mình là kiểm tra xem tôi đã xác định ánh xạ JPA chính xác chưa. Tôi không sử dụng một khuôn khổ mocking cho các thử nghiệm này, tôi sử dụng khung kiểm tra Spring thực sự khởi động vùng chứa cho phép tôi tự động lưu trữ kho thực sự vào bài kiểm tra Junit để tôi có thể thực hiện các kiểm tra đối với nó.

Tôi đồng ý với suy nghĩ của bạn rằng việc nhái kho lưu trữ là khá vô ích. Kể từ khi bạn sử dụng Spring, tôi sẽ đề xuất sử dụng Spring Test framework để thực hiện các kiểm thử thực đối với các kho lưu trữ của bạn, có thể được thực thi dựa trên cơ sở dữ liệu nhúng như H2 trong một thời gian thử nghiệm đơn vị hơn hoặc triển khai cơ sở dữ liệu thực tế của bạn như Oracle hoặc MySql. tiến hành thử nghiệm tích hợp hơn. (Thực hiện những điều này chống lại một bản sao của một cơ sở dữ liệu phát triển) Các thử nghiệm này sẽ tiết lộ các sự thất bại trong ánh xạ JPA của bạn và các mục khác như thiết lập cascades không đúng trong cơ sở dữ liệu.

Đây là một example của một trong các thử nghiệm của tôi trên GitHub. Lưu ý cách khung thực sự tự động lưu trữ kho lưu trữ vào thử nghiệm. Kho lưu trữ cũng chứa một ví dụ về cách cấu hình khung kiểm tra Spring, mà tôi cũng đã chứng minh trong số này blog post.

Tóm lại, tôi không tin rằng bạn sẽ nhận được bất kỳ lợi ích nào của việc thử nghiệm kho lưu trữ mà tôi đã thảo luận từ việc sử dụng kho lưu trữ.

Một lưu ý bổ sung mà tôi muốn thêm vào, đó là các mock không thực sự được dùng để sử dụng trong lớp thực tế đang được kiểm tra. Việc sử dụng chúng là để cung cấp các phụ thuộc cần thiết cho một lớp đang được kiểm tra.

+0

Có, tôi có toàn bộ các bài kiểm tra tích hợp sử dụng SpringJUnitTestRunner và các kho lưu trữ thực. ở đây tôi đang cố gắng để đơn vị kiểm tra dịch vụ mà nội bộ sử dụng một kho lưu trữ. Dự án của tôi yêu cầu postgresql để cơ sở dữ liệu trong bộ nhớ sẽ không hoạt động. Nhưng theo như tôi có thể nói bạn đồng ý rằng thử nghiệm đơn vị ví dụ trên là ít nhiều vô giá trị? –

+0

@beginner_ Có, tôi không thấy điểm trong đó. –

+0

Sau khi đọc câu trả lời này một lần nữa tôi nghĩ rằng bạn hiểu lầm tôi. Tôi đang thử nghiệm một dịch vụ sử dụng kho lưu trữ và không phải là kho lưu trữ, do đó nó sẽ nhại nó. –

1

Bạn chính xác. Nó là đơn vị kiểm tra rõ ràng. Và nó sẽ không bao giờ thất bại (vì vậy, nó vô ích) Tôi nghĩ bạn cần kiểm tra tích hợp để kiểm tra bất động sản Kho lưu trữ JPA với cơ sở dữ liệu thực (ví dụ: H2) (như tôi luôn làm).

Và tốt hơn là nên kiểm tra dịch vụ của bạn (giao diện của họ). Nếu sau một thời gian, bạn sẽ thay đổi bộ nhớ của mình (ví dụ như Mongo) - bạn sẽ có thể sử dụng các thử nghiệm dịch vụ của mình để đảm bảo tất cả các công việc như trước đây.

Sau một thời gian, bạn sẽ ngạc nhiên khi có bao nhiêu vấn đề liên quan đến DB \ JPA (ràng buộc, khóa lạc quan, tải lười, id trùng lặp, một số vấn đề ngủ đông và vân vân).

Ngoài ra, hãy thử phát triển thông qua các bài kiểm tra - không chỉ viết bài kiểm tra sau khi triển khai. Thay vào đó, trước khi tạo phương thức mới trong dịch vụ - hãy tạo thử nghiệm cho nó, thực hiện phương thức dịch vụ và chỉ sau khi kiểm tra lại nó trong ứng dụng thực. Ít nhất thì bắt đầu thử nghiệm nhanh hơn nhiều so với máy chủ.

Vì vậy, không tạo các thử nghiệm để có nhiều thử nghiệm. Tìm cách họ có thể giúp bạn.

Việc sử dụng mocks cho kho lưu trữ không phải là ý tưởng hay. Kiểm tra cách các dịch vụ của bạn làm việc cùng với Hibernate \ JPA \ Database. Hầu hết các vấn đề nằm ở các lớp beetwen.

+0

cảm ơn nhận xét của bạn và tôi đồng ý. Như đã đề cập trong các bình luận khác, tôi đã có một loạt các bài kiểm tra tích hợp và các vấn đề cấu hình và tương tác giữa các thành phần là tốt. Tôi mới để thử nghiệm và cố gắng để xác định xem tôi thậm chí cần thử nghiệm đơn vị ở đây hoặc chỉ cần làm thử nghiệm tích hợp thẳng mà đòi hỏi postgresql + và add-on cho nó sẽ được cài đặt. Điều duy nhấtcác thử nghiệm ví dụ làm là để xác định nếu ai đó vô tình messed lên báo cáo trở lại như 'return null;' hoặc một cái gì đó tương tự ngu ngốc hoặc không. –

+1

Nhưng đôi khi thử nghiệm đơn vị rất helfull. Ví dụ nếu bạn đã sửa lỗi - trước khi đẩy nó vào kho lưu trữ - hãy tạo đơn vị (nếu có thể) hoặc kiểm tra tích hợp cho nó. Và trong khoảng 30% các trường hợp bạn sẽ ngạc nhiên :) –

8

Câu hỏi có thể hơi cũ nhưng tôi sẽ đặt câu trả lời trong trường hợp ai đó tình cờ gặp phải.

  • Tôi đang sử dụng Mockito và JUnit.
  • AccountRepository là một kho lưu trữ dữ liệu xuân đơn giản mở rộng JPARepository.
  • Tài khoản là thực thể JPA đơn giản.

Để kiểm tra dịch vụ của bạn và giả lập kho dữ liệu Spring, bạn cần một cái gì đó như dưới đây.

package foo.bar.service.impl; 

import foo.bar.data.entity.Account; 
import foo.bar.data.repository.AccountRepository; 
import foo.bar.service.AccountService; 

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.mockito.runners.MockitoJUnitRunner; 

@RunWith(MockitoJUnitRunner.class) 
public class AccountServiceImplTest { 

    @Mock 
    private static AccountRepository accountRepository; 

    @InjectMocks 
    private static AccountService accountService = new AccountServiceImpl(); 

    private Account account; 

    @Test 
    public void testFindAccount() { 

     Integer accountId = new Integer(1); 

     account = new Account(); 
     account.setId(accountId); 
     account.setName("Account name"); 
     account.setCode("Accont code"); 
     account.setDescription("Account description"); 

     Mockito.when(accountRepository.findOne(accountId)).thenReturn(account); 

     Account retrivedAccount = accountService.findAccount(accountId); 

     Assert.assertEquals(account, retrivedAccount); 

    } 

} 
+0

Điều này khiến tôi hầu như ở đó. Tôi cũng tìm thấy url này hữu ích: http://lkrnac.net/blog/2014/01/mock-autowired-fields/ –

1

Bạn có thể sử dụng thư viện này: https://github.com/agileapes/spring-data-mock

này sẽ nhạo báng kho cho bạn, đồng thời cho phép bạn thực hiện các chức năng tùy chỉnh cho bất kỳ phương pháp cũng như các phương pháp truy vấn mẹ đẻ của bạn.

Các vấn đề liên quan