2011-12-28 40 views
6

Tôi đang viết các bài kiểm tra đơn vị cho lớp dịch vụ trong ứng dụng mùa xuân của tôi.
Đây là lớp dịch vụ của tôiKiểm thử đơn vị với Mockito

@Service 
    public class StubRequestService implements RequestService {  
     @Autowired 
     private RequestDao requestDao; 

     @Transactional(propagation = Propagation.REQUIRED, readOnly = true) 
     @Override 
     public Request getRequest(Long RequestId) { 
      Request dataRequest = requestDao.find(requestId); 
      return dataRequest; 
     } 
    } 

Đây là lớp học thử nghiệm của tôi

@RunWith(MockitoJUnitRunner.class) 
@ContextConfiguration(locations = { "/META-INF/spring/applicationContext.xml" }) 
public class StubRequestServiceTest { 

    @Mock 
    public RequestDao requestDao; 

    StubRequestService stubRequestService; // How can we Autowire this ? 

    @org.junit.Before 
    public void init() { 
     stubRequestService = new StubRequestService(); // to avoid this 
     stubRequestService.setRequestDao(dataRequestDao); 
     // Is it necessary to explicitly set all autowired elements ? 
     // If I comment/remove above setter then I get nullPointerException 
    } 

    @Test 
    public void testGetRequest() { 
     Request request = new Request(); 
     request.setPatientCnt("3"); 
     when(requestDao.find(anyLong())).thenReturn(request); 
     assertEquals(stubRequestService.getRequest(1234L).getPatientCnt(),3); 
    }  
} 

của nó làm việc vài câu hỏi tốt nhưng tôi có

  1. Làm thế nào chúng ta có thể Autowire lớp dịch vụ trong thử nghiệm? Tôi đang sử dụng hàm tạo trong phương thức init() để tạo đối tượng dịch vụ.
  2. Chúng tôi có phải đặt tất cả thành phần Autowire cho lớp dịch vụ không? Ví dụ: StubRequestService có autowired RequestDao mà tôi cần phải đặt rõ ràng trước khi gọi phương thức thử nghiệm nếu không nó đã được cung cấp nullPointerExceptionrequestDaonull trong phương thức StubRequestService.getRequest.
  3. Thực tiễn tốt để làm theo trong khi kiểm tra đơn vị lớp dịch vụ mùa xuân là gì? (Nếu tôi làm gì sai).
+0

Nếu bạn thay đổi câu hỏi của bạn sau khi các câu trả lời được đưa ra, câu trả lời không có ý nghĩa nhiều nữa. Tôi sẽ khôi phục bản chỉnh sửa cuối cùng của bạn. –

+0

@JB: Xin lỗi vì đã chỉnh sửa câu hỏi. Tôi chỉ muốn cung cấp thông tin chính xác và chính xác. Cảm ơn – xyz

Trả lời

3
  1. Nếu bạn thực sự cảm thấy nó sẽ làm cho bài kiểm tra của bạn dễ hiểu hơn - bạn có thể khởi tạo ngữ cảnh mùa xuân và tìm nạp tất cả các đối tượng từ đó. Tuy nhiên, thông thường nó sẽ yêu cầu tạo một tệp cấu hình XML riêng biệt cho các bài kiểm tra do đó tôi sẽ không khuyến khích nó.

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("testApplicationContext.xml"); 
    stubRequestService = (RequestService)applicationContext.getBean("myRequestServiceBean"); 
    
  2. (và 3) Về cơ bản, tôi thích thử nghiệm mỗi thành phần của ứng dụng của tôi trong cô lập hoàn toàn từ eachother và đó là lý do tại sao tôi không có gợi ý gì tôi đã mô tả trong [1].

Điều đó có nghĩa là bạn phải mất một lát logic riêng biệt của ứng dụng của bạn và kiểm tra chỉ nó, trong khi đầy đủ mocking lên tất cả mọi thứ nó cố gắng truy cập.

Hãy nói rằng bạn có ba lớp:

//Fetches stuff from some webservice and converts to your app domain POJOs 
class DataAccessLayer { 
    public void setWebservice(Webservice ws) {...}; 

    public MyObject getMyObject() {...}; 
} 

//Formats the domain POJOs and sends them to some kind of outputstream or stuff. 
class ViewLayer { 
    public void setOutputStream(OutputStream os) {...}; 

    public void viewMyObject(MyObject mo) {...}; 
} 

//Main entry point of our MyObject fetch-process-display workflow 
class Controller { 
    public void setDataAccessLayer(DataAccessLayer dal) {...}; 
    public void setViewLayer(ViewLayer vl) {...}; 

    public void showMyObject() { 
     MyObject mo = dal.getMyObject(); 
     ...some processing here maybe... 
     vl.viewMyObject(mo); 
    } 
} 

Bây giờ, những gì có thể kiểm tra chúng tôi viết ở đây?

  1. Kiểm tra xem DataAccessLayer đúng cách chuyển đổi các đối tượng từ chế nhạo lên WS để đối tượng miền của chúng tôi.
  2. Kiểm tra xem có ViewLayer định dạng đúng đối tượng được cung cấp cho anh ấy và ghi nó vào giả lập luồng đầu ra.
  3. Kiểm tra xem Controller mất một đối tượng từ chế nhạo lênDataAccessLayer quá trình nó đúng và gửi nó đến chế nhạo lênViewLayer.
+0

Có lý do cụ thể nào để sử dụng tệp ngữ cảnh khác nhau để khởi tạo bean trong thử nghiệm không? Và cảm ơn ví dụ. Nó thực sự đã giúp rất nhiều. – xyz

+0

Không có lý do gì, nó chỉ xảy ra là nó không tương thích với các bài kiểm tra của bạn. Ví dụ, nó đòi hỏi một số tài nguyên JNDI, có thể tải một số cơ sở dữ liệu (và thử nghiệm không bao giờ sử dụng chúng), có thể một số bảo mật. Vì vậy, cuối cùng bạn chỉ đơn giản là bắt đầu nhận thấy rằng nó dễ dàng hơn để tạo ra một tập tin ngữ cảnh riêng biệt để thử nghiệm. – bezmax

+0

Có, có một lý do: bạn không muốn thử nghiệm một dịch vụ với DAO thực. Bạn muốn có một DAO giả để kiểm tra dịch vụ. Nhưng hãy làm theo lời khuyên của Max và của tôi: không sử dụng bối cảnh mùa xuân cho các dịch vụ thử nghiệm đơn vị. Bạn có thể muốn một bối cảnh Spring để tiêm một Datasource, SessionFactory và TxManager trong các bài kiểm tra DAO, nhưng không phải trong các thử nghiệm dịch vụ. –

7

Bài kiểm tra của bạn là tốt. Nó thậm chí không cần phải có chú thích @ContextConfiguration.

Toàn bộ khuôn khổ của khuôn khổ tiêm phụ thuộc như Spring là có thể đơn vị dịch vụ thử nghiệm bằng cách đơn giản hóa chúng, thiết lập phụ thuộc giả, và sau đó gọi phương thức của chúng.

Bạn đang thực hiện chính xác. Bạn không cần phải có một bối cảnh mùa xuân cho các bài kiểm tra đơn vị như vậy. Đó là lý do tại sao họ được gọi là kiểm tra đơn vị: họ kiểm tra nó trong sự cô lập của tất cả các phụ thuộc thực tế của họ, Spring bao gồm.

Lưu ý phụ: giả sử bạn đang sử dụng JUnit, các đối số của phương thức assertXxx sẽ được hoán đổi. Giá trị kỳ vọng xuất hiện trước giá trị thực tế. Nó trở nên quan trọng khi xác nhận không thành công và bạn có một thông báo như "mong đợi 6 nhưng là 3" thay vì "mong đợi 3 nhưng là 6".

+0

Cảm ơn bạn đã trả lời và đề xuất. Có nghĩa là chúng ta nên tạo một cách rõ ràng đối tượng dịch vụ và thiết lập tất cả phụ thuộc tự động? Tôi đang được khuyên để autowire nó thay vì thiết lập nó bằng tay. – xyz

+1

Autowiring là OK khi chạy ứng dụng. Nó không cần thiết, hoặc thậm chí mong muốn, khi thử nghiệm đơn vị, vì mọi thử nghiệm sẽ muốn tiêm các phụ thuộc giả lập của riêng nó. –

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