Tôi mới bắt đầu tìm hiểu về Mockito hôm nay. Tôi đã viết một số thử nghiệm đơn giản (với JUnit, xem bên dưới), nhưng tôi không thể tìm ra cách tôi có thể sử dụng đối tượng giả bên trong các bean được quản lý của Spring. Các phương pháp hay nhất để làm việc với Spring là gì. Làm thế nào tôi nên tiêm sự phụ thuộc chế nhạo vào bean của tôi?
Bạn có thể bỏ qua điều này cho đến khi quay lại câu hỏi của tôi .
Trước hết, những gì tôi đã học được. Đây là bài viết rất hay Mocks Aren't Stubs giải thích những điều cơ bản (Mock's kiểm tra xác minh hành vi không phải xác minh trạng thái ). Sau đó, có một ví dụ điển hình ở đây Mockito và ở đây Chế giễu dễ dàng hơn với mockito . Chúng tôi có lời giải thích rằng các đối tượng giả của Mockito đều là giả và sơ khai .
Tại đây Mockito và đây Matchers , bạn có thể tìm thêm các ví dụ khác.
Bài kiểm tra này
@Test
public void testReal(){
List<String> mockedList = mock(List.class);
//stubbing
//when(mockedList.get(0)).thenReturn("first");
mockedList.get(anyInt());
OngoingStubbing<String> stub= when(null);
stub.thenReturn("first");
//String res = mockedList.get(0);
//System.out.println(res);
//you can also verify using argument matcher
//verify(mockedList).get(anyInt());
verify(mockedList);
mockedList.get(anyInt());
}
hoạt động tốt.
Trở lại câu hỏi của tôi. Ở đây Tiêm Mockito mock vào một Spring bean ai đó cố gắng sử dụng Springs ReflectionTestUtils.setField()
, nhưng sau đó ở đây Spring Integration Tests, Tạo Mock Object, chúng tôi khuyên bạn nên thay đổi ngữ cảnh của Spring.
Tôi thực sự không hiểu hai liên kết cuối cùng ... Ai đó có thể giải thích cho tôi vấn đề Spring có gì với Mockito không? Có gì sai với giải pháp này?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
CHỈNH SỬA : Tôi không thực sự rõ ràng. Tôi sẽ cung cấp 3 ví dụ về mã để làm rõ bản thân của tôi: Giả sử, chúng ta có bean HelloWorld với phương thức printHello()
và bean HelloFacade với phương thức sayHello
chuyển tiếp các cuộc gọi đến phương thức của HelloWorld printHello()
.
Ví dụ đầu tiên là sử dụng ngữ cảnh của Spring và không có trình chạy tùy chỉnh, sử dụng ReflectionTestUtils để tiêm phụ thuộc (DI):
public class Hello1Test {
private ApplicationContext ctx;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}
@Test
public void testHelloFacade() {
HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
HelloWorld mock = mock(HelloWorld.class);
doNothing().when(mock).printHello();
ReflectionTestUtils.setField(obj, "hello", mock);
obj.sayHello();
verify(mock, times(1)).printHello();
}
}
Như @Noam đã chỉ ra có cách để chạy nó bằng cách gọi rõ ràng tới MockitoAnnotations.initMocks(this);
. Tôi cũng sẽ bỏ sử dụng bối cảnh của Spring trong ví dụ này.
@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {
@InjectMocks
private HelloFacade obj = new HelloFacadeImpl();
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
Một cách khác để làm điều này
public class Hello1aTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@InjectMocks
private HelloFacadeImpl obj;
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
Không, trong ví dụ trước, chúng tôi phải cài đặt thủ công HelloFacadeImpl và gán nó cho HelloFacade, vì HelloFacade là giao diện. Trong ví dụ cuối cùng, chúng ta chỉ có thể khai báo HelloFacadeImpl và Mokito sẽ khởi tạo nó cho chúng ta. Hạn chế của phương pháp này là hiện nay, unit-under-test là impl-class chứ không phải interface.
@InjectMocks
(tương đối gần đây, mặc dù IIRC trước bài đăng trên blog đó) nên có những trường hợp cần sắp xếp lại các định nghĩa bean có thể là cần thiết. Tôi không chắc câu hỏi rốt cuộc là gì.