Mockito – doReturn()和when()之间的区别

我目前正在使用Mockito在我想testing我的Controller方法的Spring MVC应用程序中模拟我的服务层对象。 然而,正如我一直在阅读Mockito的具体细节,我发现方法doReturn(...).when(...)等于when(...).thenReturn(...) 。 所以,我的问题是有两个方法做同样的事情或什么是doReturn(...).when(...)之间的细微差别是什么doReturn(...).when(...)when(...).thenReturn(...)

任何帮助,将不胜感激。

两种用于存根的语法大致相同。 但是,您可以随时使用doReturn/when for doReturn/when ; 但有些情况下,你不能使用when/thenReturn 。 虚空方法就是这样的一个例子。 其他的包括与Mockito间谍一起使用,并且不止一次地用相同的方法存根。

有一件事, when/thenReturn给你,那么doReturn/when时候不,是在编译时检查你返回的值的types检查。 不过,我相信这几乎是没有价值的 – 如果你的types错了,你会发现一旦你运行你的testing。

我强烈build议只使用doReturn/when 。 学习两种语法是没有意义的。

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

如果您使用spied对象(使用@Spy注释)而不是模拟(使用@Mock注释),则两种方法的行为@Spy

  • when(...) thenReturn(...)在返回指定值之前进行实际的方法调用 。 所以如果被调用的方法抛出一个exception,你必须处理它/模拟它等等。当然,你仍然得到你的结果(你在thenReturn(...)定义的)

  • doReturn(...) when(...) 根本不调用该方法

例:

 public class MyClass { protected String methodToBeTested() { return anotherMethodInClass(); } protected String anotherMethodInClass() { throw new NullPointerException(); } } 

testing:

 @Spy private MyClass myClass; // ... // would work fine doReturn("test").when(myClass).anotherMethodInClass(); // would throw a NullPointerException when(myClass.anotherMethodInClass()).thenReturn("test"); 

后面的替代方法用于返回void

请看看,例如,在这里: 如何使模拟无效方法与mockito

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

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

所以当方法在同一个testing用例中被调用时,它将返回false,然后它将再次返回false,并且最后是true。

Mockito javadoc似乎告诉了为什么使用doReturn()而不是when()在不能使用Mockito.when(Object)的情况下,在那些罕见的情况下使用doReturn()。

注意Mockito.when(Object)总是被推荐用于存根,因为它是参数types安全的并且更具可读性(特别是当连续调用存根时)。

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

当间谍侦察真实的对象和调用真正的方法带来副作用

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());

//不可能:调用exception存根foo()方法,引发RuntimeException。 when(mock.foo()).thenReturn("bar");

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

doReturn("bar").when(mock).foo(); 以上场景展示了Mockito优雅语法的折衷。 请注意,情景是非常罕见的,虽然。 间谍应该是零星的,压倒一切的例外情况非常罕见。 更不用说,一般来说,被覆盖的残片是一种潜在的代码味道,指出了太多的残片。

“模拟”可以模拟一个对象,而不是创build它;“间谍”可以创build一个具有实际参数的实际对象。 当我们做unit testing时,我们经常使用它们。 但是,当(xxx).thenReturn(xxx)'用于模拟,'doReturn(xxx).when(xxx)'用于间谍。