我目前正在使用Mockito在Spring MVC应用程序中模拟我的服务层对象,我想在其中测试我的Controller方法。然而,当我一直在阅读Mockito的细节时,我发现doReturn(…).when(…)方法等价于when(…).then return(…)。所以,我的问题是,有两个方法做同样的事情有什么意义,或者doReturn(…).when(…)和when(…).thenReturn(…)之间有什么微妙的区别?

任何帮助都将不胜感激。


后一种选择用于返回void的模拟方法。

请看下面的例子: 如何使mock无效的方法与mockito


这两种存根语法大致相同。然而,你总是可以使用doReturn/when进行存根;但是有些情况下你不能使用when/thenReturn。Stubbing void方法就是其中之一。其他包括与Mockito间谍一起使用,并多次使用相同的方法。

when/thenReturn给了你一件事,doReturn/when没有,那就是在编译时对你返回的值进行类型检查。但是,我相信这几乎没有任何价值——如果您弄错了类型,您将在运行测试时立即发现。

我强烈建议只使用doReturn/when。当一种语法就可以的时候,学习两种语法是没有意义的。

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


如果你使用间谍对象(带有@Spy注释)而不是mock对象(带有@Mock注释),这两种方法的表现都不同:

当(…)thenReturn(…)在返回指定值之前调用一个真正的方法。所以如果被调用的方法抛出异常,你必须处理它/模拟它等等。当然,你仍然会得到你的结果(你在thenReturn(…)中定义的结果) doReturn(…)当(…)根本不调用该方法时。

例子:

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

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

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

在同一个测试用例中调用这个方法时,它会返回false然后再次返回false,最后返回true。


Mockito javadoc似乎告诉我们为什么使用doReturn()而不是when() 在不能使用Mockito.when(Object)的极少数情况下使用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). Here are those rare occasions when doReturn() comes handy: 1. When spying real objects and calling real methods on a spy brings side effects List list = new LinkedList(); List spy = spy(list); //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); //You have to use doReturn() for stubbing: doReturn("foo").when(spy).get(0); 2. Overriding a previous exception-stubbing: when(mock.foo()).thenThrow(new RuntimeException()); //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown. when(mock.foo()).thenReturn("bar"); //You have to use doReturn() for stubbing: doReturn("bar").when(mock).foo(); Above scenarios shows a tradeoff of Mockito's elegant syntax. 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.