Mockito - doReturn()和when()之间的差异

我目前正在使用Mockito在Spring MVC应用程序中模拟我的服务层对象,我想在其中测试我的Controller方法。然而,当我阅读Mockito的细节时,我发现doReturn(...).when(...)方法等价于when(...).thenReturn(...)方法。所以,我的问题是,有两个方法做同样的事情有什么意义,或者doReturn(...).when(...)when(...).thenReturn(...)之间有什么微妙的区别?

任何帮助都将不胜感激。

231969 次浏览

后一种替代方法用于返回void的模拟方法。

请看,例如,这里: 如何使mock无效的方法与mockito < / p >

这两种存根语法大致相同。然而,你可以总是使用doReturn/when进行存根;但有些情况下,你不能使用when/thenReturn。Stubbing void方法就是其中之一。其他包括与Mockito间谍一起使用,并多次使用相同的方法。

有一件事when/thenReturn给了你,而doReturn/when没有,那就是在编译时对你返回的值进行类型检查。但是,我相信这几乎没有任何价值——如果您弄错了类型,您将在运行测试时立即发现。

我强烈建议只使用doReturn/when。当一种语法就可以的时候,学习两种语法是没有意义的。

你可能希望参考我在形成Mockito“语法”;的回答——对一个非常密切相关的问题的更详细的回答。

如果使用间谍对象(用@Spy注释)而不是mock对象(用@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");

继续这个答案,还有另一个区别,如果你想让你的方法返回不同的值,比如第一次调用,第二次调用等等,那么你可以传递值,例如…

PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));

在同一个测试用例中调用这个方法时,它会返回false然后再次返回false,最后返回true。

Mockito javadoc似乎告诉我们为什么使用doReturn()而不是when() 在不能使用Mockito.when(Object)的极少数情况下使用doReturn()。< / p >
注意Mockito.when(Object)总是推荐用于存根 因为它是参数类型安全的,更可读(特别是当 连续呼叫存根)。< / p >

以下是doReturn()派上用场的罕见情况:

当间谍真实的对象和调用一个间谍带来的真正的方法时 影响< / p >

List list = new LinkedList(); List spy = spy(list);

//不可能:真实方法被称为so spy.get(0)抛出 IndexOutOfBoundsException(列表仍然为空)

when(spy.get(0)).thenReturn("foo");

//你必须使用doReturn()进行存根: doReturn("foo").when(spy).get(0); < / p >

2.重写之前的异常存根:

when(mock.foo()).thenThrow(new RuntimeException());

//不可能:异常存根的foo()方法被调用so 抛出RuntimeException。when(mock.foo()).thenReturn("bar"); < / p >

//你必须使用doReturn()进行存根:

doReturn("bar").when(mock).foo();上述场景显示了一个权衡 Mockito优雅的语法。请注意,这种情况非常罕见, 虽然。间谍活动应该是零星的,最重要的例外是捣毁 非常罕见的。更不用说,在一般情况下,覆盖存根是一个

.

.