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

时间:2013-12-03 14:28:48

标签: java unit-testing mockito

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

任何帮助都将不胜感激。

6 个答案:

答案 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)'用于间谍。