简体   繁体   English

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

[英]Mockito - difference between doReturn() and when()

I am currently in the process of using Mockito to mock my service layer objects in a Spring MVC application in which I want to test my Controller methods.我目前正在使用 Mockito 在 Spring MVC 应用程序中模拟我的服务层对象,我想在其中测试我的控制器方法。 However, as I have been reading on the specifics of Mockito, I have found that the methods doReturn(...).when(...) is equivalent to when(...).thenReturn(...) .然而,当我一直在阅读 Mockito 的细节时,我发现方法doReturn(...).when(...)等效于when(...).thenReturn(...) So, my question is what is the point of having two methods that do the same thing or what is the subtle difference between doReturn(...).when(...) and when(...).thenReturn(...) ?所以,我的问题是让两种方法做同样的事情有什么意义,或者doReturn(...).when(...)when(...).thenReturn(...) ?

Any help would be appreciated.任何帮助将不胜感激。

The two syntaxes for stubbing are roughly equivalent.存根的两种语法大致相同。 However, you can always use doReturn/when for stubbing;但是,您始终可以使用doReturn/when进行存根; but there are cases where you can't use when/thenReturn .但有些情况下您不能使用when/thenReturn Stubbing void methods is one such.存根 void 方法就是这样一种方法。 Others include use with Mockito spies, and stubbing the same method more than once.其他包括与 Mockito 间谍一起使用,并多次使用相同的方法。

One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. when/thenReturn给你的一件事是在编译时对你返回的值进行类型检查,而doReturn/when没有。 However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test.但是,我相信这几乎没有任何价值 - 如果您的类型错误,您会在运行测试后立即发现。

I strongly recommend only using doReturn/when .我强烈建议只使用doReturn/when There is no point in learning two syntaxes when one will do.当一种语法可以学习时,学习两种语法是没有意义的。

You may wish to refer to my answer at Forming Mockito "grammars" - a more detailed answer to a very closely related question.您可能希望参考我在Forming Mockito “grammars” 中的回答 - 对一个非常密切相关的问题的更详细的回答。

Both approaches behave differently if you use a spied object (annotated with @Spy ) instead of a mock (annotated with @Mock ):如果您使用被监视的对象(用@Spy注释)而不是模拟(用@Mock注释),两种方法的行为会有所不同:

  • when(...) thenReturn(...) makes a real method call just before the specified value will be returned. when(...) thenReturn(...)在返回指定值之前进行真正的方法调用 So if the called method throws an Exception you have to deal with it / mock it etc. Of course you still get your result (what you define in thenReturn(...) )所以如果被调用的方法抛出一个异常,你必须处理它/模拟它等等。当然你仍然得到你的结果(你在thenReturn(...)定义的)

  • doReturn(...) when(...) does not call the method at all . doReturn(...) when(...)根本不调用该方法

Example:示例:

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

     protected String anotherMethodInClass() {
          throw new NullPointerException();
     }
}

Test:测试:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

The Mockito javadoc seems to tell why use doReturn() instead of when() Use doReturn() in those rare occasions when you cannot use Mockito.when(Object). Mockito javadoc 似乎说明了为什么在无法使用 Mockito.when(Object) 的极少数情况下使用doReturn()而不是when()使用 doReturn()。

Beware that Mockito.when(Object) is always recommended for stubbing because it is argument type-safe and more readable (especially when stubbing consecutive calls).请注意,始终建议将 Mockito.when(Object) 用于存根,因为它是参数类型安全的且更具可读性(尤其是在存根连续调用时)。

Here are those rare occasions when doReturn() comes handy:以下是 doReturn() 派上用场的罕见情况:

1. When spying real objects and calling real methods on a spy brings side effects 1.当spy真正的对象,在spy上调用真正的方法会带来副作用

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

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) //不可能:真正的方法被调用所以spy.get(0)抛出IndexOutOfBoundsException(列表还为空)

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

//You have to use doReturn() for stubbing: doReturn("foo").when(spy).get(0); //您必须使用 doReturn() 进行存根: doReturn("foo").when(spy).get(0);

2. Overriding a previous exception-stubbing: 2.覆盖之前的异常存根:

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

//Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown. //不可能:调用异常存根的 foo() 方法因此抛出 RuntimeException。 when(mock.foo()).thenReturn("bar");

//You have to use doReturn() for stubbing: //您必须使用 doReturn() 进行存根:

doReturn("bar").when(mock).foo(); Above scenarios shows a tradeoff of Mockito's elegant syntax.以上场景显示了 Mockito 优雅语法的权衡。 Note that the scenarios are very rare, though.但请注意,这种情况非常罕见。 Spying should be sporadic and overriding exception-stubbing is very rare.监视应该是零星的,并且覆盖异常存根是非常罕见的。 Not to mention that in general overridding stubbing is a potential code smell that points out too much stubbing.更不用说一般来说,覆盖存根是一种潜在的代码异味,指出存根过多。

Continuing this answer , There is another difference that if you want your method to return different values for example when it is first time called, second time called etc then you can pass values so for example...继续这个答案,还有另一个区别,如果您希望您的方法返回不同的值,例如第一次调用,第二次调用等时,那么您可以传递值,例如...

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

So it will return false when the method is called in same test case and then it will return false again and lastly true.因此,当在同一测试用例中调用该方法时,它将返回 false,然后再次返回 false,最后返回 true。

The latter alternative is used for methods on mocks that return void .后一种替代方法用于返回void模拟方法。

Please have a look, for example, here: How to make mock to void methods with mockito请看一下,例如,这里: How to make mock to void methods with mockito

"mock" can simulate a object instead of create it;"spy" can create a actual object with actual parameters. “mock”可以模拟对象而不是创建它;“spy”可以创建具有实际参数的实际对象。 When we do unit test,we often use them. 当我们进行单元测试时,我们经常使用它们。 But 'when(xxx).thenReturn(xxx)' used for mock and 'doReturn(xxx).when(xxx)' used for spy. 但'when(xxx).thenReturn(xxx)'用于模拟和'doReturn(xxx).when(xxx)'用于间谍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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