繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM