我目前正在使用Mockito来模拟Spring MVC应用程序中的服务层对象,我想在其中测试我的Controller方法。但是,正如我一直在阅读Mockito的细节,我发现方法doReturn(...).when(...)
等同于when(...).thenReturn(...)
。所以,我的问题是,有两种方法可以做同样的事情,或者doReturn(...).when(...)
和when(...).thenReturn(...)
之间的细微差别是什么?
任何帮助都将不胜感激。
答案 0 :(得分:182)
存根的两种语法大致相同。但是,您可以始终使用doReturn/when
进行存根;但有些情况下无法使用when/thenReturn
。挖空虚方法就是这样。其他包括与Mockito间谍一起使用,并且不止一次地使用相同的方法。
when/thenReturn
给你的一件事doReturn/when
没有,是在编译时对你返回的值进行类型检查。但是,我相信这几乎没有任何价值 - 如果你的类型错了,你会在你进行测试后立即发现。
我强烈建议您仅使用doReturn/when
。在学习两种语法时没有意义。
您可能希望在Forming Mockito "grammars"上参考我的回答 - 对一个非常密切相关的问题进行更详细的回答。
答案 1 :(得分:145)
如果您使用间谍对象(使用@Spy
注释)而不是模拟(使用@Mock
注释),两种方法的行为都会有所不同:
when(...) thenReturn(...)
在返回指定值之前进行真正的方法调用。因此,如果被调用的方法抛出异常,你必须处理它/模拟它等。当然你仍然得到你的结果(你在thenReturn(...)
中定义的)
doReturn(...) when(...)
根本不会调用该方法。
示例:
public class MyClass {
protected String methodToBeTested() {
return anotherMethodInClass();
}
protected String anotherMethodInClass() {
throw new NullPointerException();
}
}
测试:
@Spy
private MyClass myClass;
// ...
// would work fine
doReturn("test").when(myClass).anotherMethodInClass();
// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");
答案 2 :(得分:9)
Mockito javadoc似乎告诉为什么使用doReturn()
代替when()
在无法使用Mockito.when(Object)的极少数情况下使用doReturn()。
请注意,Mockito.when(Object)始终建议用于存根 因为它是参数类型安全且更具可读性(尤其是当 连续打电话)。
以下是doReturn()出现的罕见场合:
1。当侦察真实物体并在间谍上调用真实方法时会带来一面 效果
List list = new LinkedList(); List spy = spy(list);
//不可能:调用真正的方法,因此spy.get(0)抛出 IndexOutOfBoundsException(列表尚未清空)
when(spy.get(0)).thenReturn("foo");
//你必须使用doReturn()进行存根:
doReturn("foo").when(spy).get(0);
2. 覆盖之前的异常存根:
when(mock.foo()).thenThrow(new RuntimeException());
//不可能:这样调用异常存根的foo()方法 抛出RuntimeException。
when(mock.foo()).thenReturn("bar");
//你必须使用doReturn()进行存根:
doReturn("bar").when(mock).foo();
以上情景显示了权衡 Mockito的优雅语法。请注意,场景非常罕见, 虽然。间谍应该是零星的,而且最重要的是例外 极少。更不用说一般来说覆盖存根是一种 潜在的代码气味,指出太多的顽固。
答案 3 :(得分:5)
后一种方法用于返回void
的模拟方法。
请看一下,例如,这里: How to make mock to void methods with mockito
答案 4 :(得分:5)
继续this answer,还有另一个区别,如果你希望你的方法返回不同的值,例如第一次调用时,第二次调用等,那么你可以传递值,例如...
PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));
因此,当在同一测试用例中调用该方法时它将返回false,然后它将再次返回false,最后返回true。
答案 5 :(得分:-2)
“mock”可以模拟对象而不是创建它;“spy”可以创建具有实际参数的实际对象。当我们进行单元测试时,我们经常使用它们。 但'when(xxx).thenReturn(xxx)'用于模拟和'doReturn(xxx).when(xxx)'用于间谍。