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

Java Mockito-doReturn()和when()之间的差异,java,unit-testing,mockito,Java,Unit Testing,Mockito,我目前正在使用Mockito在SpringMVC应用程序中模拟我的服务层对象,我想在其中测试我的控制器方法。然而,正如我一直在阅读Mockito的细节一样,我发现方法doReturn(…).when(…)相当于when(…)。然后返回(…)。所以,我的问题是,有两个方法做相同的事情有什么意义,或者doReturn(…)。when(…)和when(…)。然后返回(…) 任何帮助都将不胜感激。后一种方法用于返回void的模拟上的方法 请看一看,例如,这里: stubing的两个语法大致相同。但是,您

我目前正在使用Mockito在SpringMVC应用程序中模拟我的服务层对象,我想在其中测试我的控制器方法。然而,正如我一直在阅读Mockito的细节一样,我发现方法
doReturn(…).when(…)
相当于
when(…)。然后返回(…)
。所以,我的问题是,有两个方法做相同的事情有什么意义,或者
doReturn(…)。when(…)
when(…)。然后返回(…)


任何帮助都将不胜感激。

后一种方法用于返回
void
的模拟上的方法

请看一看,例如,这里:
stubing的两个语法大致相同。但是,您始终可以使用
doReturn/when
进行存根;但在某些情况下,您不能在/when/thenReturn时使用
。存根无效方法就是这样一种方法。其他包括与Mockito间谍一起使用,以及多次使用相同的方法

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

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


您可能希望参考我的答案-一个非常密切相关问题的更详细答案。

如果您使用间谍对象(用
@Spy
注释)而不是模拟对象(用
@mock
注释),则这两种方法的行为不同:

  • 当(…)然后返回(…)
    在返回指定值之前进行实际方法调用。因此,如果被调用的方法抛出异常,您必须处理它/模拟它等。当然,您仍然会得到结果(您在
    中定义的内容,然后返回(…)

  • doReturn(…)当(…)
    根本不调用该方法时

例如:

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

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}
测试:

继续,还有另一个区别,如果您希望您的方法返回不同的值,例如第一次调用时,第二次调用时,等等,那么您可以传递值,例如

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

因此,当在同一测试用例中调用该方法时,它将返回false,然后再次返回false,最后返回true。

Mockito javadoc似乎告诉我们为什么要使用
doReturn()
而不是
when()
在少数无法使用Mockito.when(Object)的情况下使用doReturn()

注意Mockito.when(Object)总是建议用于存根 因为它是参数类型安全的,可读性更强(特别是在 中断连续呼叫)

以下是doReturn()非常有用的情况:

1.在间谍端监视真实对象并调用真实方法时 影响

List List=newlinkedlist();列表间谍=间谍(列表)

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

when(spy.get(0))。然后返回(“foo”)

//必须使用doReturn()进行存根:
doReturn(“foo”).when(spy).get(0)

2.覆盖以前的异常存根:

when(mock.foo()).thenthow(newruntimeexception())

//不可能:异常存根foo()方法被称为so 引发RuntimeException<代码>何时(mock.foo())。然后返回(“bar”)

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

doReturn(“bar”).when(mock).foo()以上场景显示了一个折衷方案
Mockito优雅的语法。请注意,这种情况非常罕见,
不过。间谍活动应该是零星的,覆盖异常存根是
非常罕见。更不用说,通常覆盖存根是一种
潜在的代码气味指出了太多的存根


javadoc有一些情况下,
doReturn()
是有用的。我认为其中一个主要区别是doReturn(…)。当(…)是一个较旧的并且不是那种类型安全的时候,我们可以在编译器不断抱怨强制转换时使用它。when(..).thenReturn(..)在类型安全性方面要好得多。这种行为只适用于间谍对象,因为它们是真实对象的“包装器”。在模拟对象的情况下,何时返回或何时返回并不重要。模拟对象从不调用真正的方法。请您提供更多信息,为什么我们需要使用此功能?我没有看到实际的用例。测试的目的是确认不同用例下代码的正确性。如果方法的calll抛出异常,测试应该抛出异常,而不是返回value@Gleichmut这是一个假设的场景,在这里我展示了doReturn的用法/优势。在实际应用程序中,只返回异常的方法当然没有意义。。但是你有一些方法(可能不像这个方法那么薄),它们在某些情况下可能会抛出异常..只是为了澄清一下:when().thenReturn()-方法只调用一次实际的方法(间谍的-对模拟不重要)。这发生在您指定模拟行为的行中(当(myClass.anotherMethodInClass().thenRet…)之后,实际方法将不再被调用。在阅读上述解释时,如果您确实希望使用一些装饰器逻辑,可能很好。这似乎不是
doReturn()的优点
,这看起来像是对库的滥用。监视而不是纯粹的模拟的目的是利用真实调用。他们还警告不要使用这样的间谍:(并建议扩展类并重写
PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));