Mockito, JUnit and Spring
我直到今天才开始了解Mockito。我写了一些简单的测试(使用JUnit,见下文),但我不知道如何在Spring的托管bean中使用模拟对象。使用Spring的最佳实践是什么?我应该如何将模拟依赖性注入我的bean?
你可以跳过这个,直到回到我的问题。
首先,我学到了什么。这是一篇非常好的文章 Mocks Isn't Stubs,它解释了基础知识(Mock的检查行为验证而不是状态验证)。然后这里有一个很好的例子 Mockito 和这里 更容易嘲笑 mockito。我们有解释,Mockito的模拟对象既是模拟的,也是存根的。
在这里Mockito和这里 Matchers,你可以找到更多的例子。
此测试
@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());
}
工作刚刚好。
回到我的问题。在这里,注入Mockito模拟到Spring bean中,有人试图使用Springs,但是在这里Spring Integration Tests,创建Mock对象,我们建议改变Spring的上下文。ReflectionTestUtils.setField()
我真的不明白最后两个链接...有人可以向我解释一下Spring对Mockito有什么问题吗?此解决方案有什么问题?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
编辑:我不太清楚。我将提供3个代码示例来澄清我的自我:假设,我们有bean HelloWorld与方法和bean HelloFacade与方法,将调用转发到HelloWorld的方法。printHello()
sayHello
printHello()
第一个例子是使用Spring的上下文,没有自定义运行器,使用ReflemEstUtils进行依赖注入(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();
}
}
正如@Noam所指出的那样,有一种方法可以在不显式调用的情况下运行它。我还将放弃在这个例子中使用Spring的上下文。MockitoAnnotations.initMocks(this);
@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();
}
}
另一种方法来做到这一点
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();
}
}
不,在预先的示例中,我们必须手动初始化HelloFacadeImpl并将其分配给HelloFacade,因为HelloFacade是接口。在最后一个示例中,我们可以只声明 HelloFacadeImpl,Mokito 将为我们实例化它。这种方法的缺点是,现在,被测单元是impl类而不是接口。