[英]Mockito - difference between doReturn() and when()
我目前正在使用 Mockito 在 Spring MVC 应用程序中模拟我的服务层对象,我想在其中测试我的控制器方法。 然而,当我一直在阅读 Mockito 的细节时,我发现方法doReturn(...).when(...)
等效于when(...).thenReturn(...)
。 所以,我的问题是让两种方法做同样的事情有什么意义,或者doReturn(...).when(...)
和when(...).thenReturn(...)
?
任何帮助将不胜感激。
存根的两种语法大致相同。 但是,您始终可以使用doReturn/when
进行存根; 但有些情况下您不能使用when/thenReturn
。 存根 void 方法就是这样一种方法。 其他包括与 Mockito 间谍一起使用,并多次使用相同的方法。
when/thenReturn
给你的一件事是在编译时对你返回的值进行类型检查,而doReturn/when
没有。 但是,我相信这几乎没有任何价值 - 如果您的类型错误,您会在运行测试后立即发现。
我强烈建议只使用doReturn/when
。 当一种语法可以学习时,学习两种语法是没有意义的。
您可能希望参考我在Forming Mockito “grammars” 中的回答 - 对一个非常密切相关的问题的更详细的回答。
如果您使用被监视的对象(用@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");
Mockito javadoc 似乎说明了为什么在无法使用 Mockito.when(Object) 的极少数情况下使用doReturn()
而不是when()
使用 doReturn()。
请注意,始终建议将 Mockito.when(Object) 用于存根,因为它是参数类型安全的且更具可读性(尤其是在存根连续调用时)。
以下是 doReturn() 派上用场的罕见情况:
1.当spy真正的对象,在spy上调用真正的方法会带来副作用
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 优雅语法的权衡。 但请注意,这种情况非常罕见。 监视应该是零星的,并且覆盖异常存根是非常罕见的。 更不用说一般来说,覆盖存根是一种潜在的代码异味,指出存根过多。
继续这个答案,还有另一个区别,如果您希望您的方法返回不同的值,例如第一次调用,第二次调用等时,那么您可以传递值,例如...
PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));
因此,当在同一测试用例中调用该方法时,它将返回 false,然后再次返回 false,最后返回 true。
后一种替代方法用于返回void
模拟方法。
请看一下,例如,这里: How to make mock to void methods with mockito
“mock”可以模拟对象而不是创建它;“spy”可以创建具有实际参数的实际对象。 当我们进行单元测试时,我们经常使用它们。 但'when(xxx).thenReturn(xxx)'用于模拟和'doReturn(xxx).when(xxx)'用于间谍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.