Java Mockito:通缉但未调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35511329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 16:45:22  来源:igfitidea点击:

Mockito: Wanted but not invoked

javaunit-testingmockito

提问by Vivin

I have a following test method:

我有以下测试方法:

MyClass myClass= Mockito.mock(MyClass.class);
Mockito.when(myClass.methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class))).thenReturn(Collections.<X, Y> emptyMap());

assertNull(myClass.methodToTest(myObject));
Mockito.verify(myClass).methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class));

The methodUsedInMethodBeingTestedis a method that I want to mock and return an empty map. But I am getting the failure message saying

methodUsedInMethodBeingTested是一种我想要模拟并返回空地图的方法。但我收到失败消息说

Wanted but not invoked myClass.methodUsedInMethodBeingTested()

通缉但未调用 myClass.methodUsedInMethodBeingTested()

.

.

MyClass
{
   public XYZ methodToTest()
   {
    ....
    ....
    Map<X,Y> mp = methodUsedInMethodBeingTested(myTypeParam);
    .....
   }

   public Map<X,Y> methodUsedInMethodBeingTested(MyTypeParam myTypeParam)
   {
    .....
   }
}

采纳答案by Tunaki

You're misunderstanding what a mock is. When you're doing

你误解了什么是模拟。当你在做

MyClass myClass = Mockito.mock(MyClass.class);
// ...
assertNull(myClass.methodToTest(myObject));

You're not actually invoking methodToTeston your real object. You're invoking methodToTeston the mock, which by default, does nothing and return null, unless it was stubbed. Quoting from Mockito docs:

你实际上并不是在调用methodToTest你的真实对象。您正在调用methodToTest模拟,默认情况下,它不执行任何操作并返回null,除非它被存根。引用Mockito 文档

By default, for all methods that return value, mock returns null, an empty collection or appropriate primitive/primitive wrapper value (e.g: 0, false, ... for int/Integer, boolean/Boolean, ...).

默认情况下,对于所有返回值的方法,mock 返回 null、一个空集合或适当的原始/原始包装值(例如:0、false、...对于 int/Integer、boolean/Boolean、...)。

This explains your subsequent error: the method was really not invoked on the mock.

这解释了您随后的错误:该方法实际上并未在模拟上调用。



It seems what you want here is a spyinstead:

看来你想要的是一个spy

You can create spies of real objects. When you use the spy then the realmethods are called (unless a method was stubbed).

您可以创建真实对象的间谍。当您使用 spy 时,将调用真正的方法(除非方法被存根)。

A note of warning though: since it is the real methods that are getting called, you should not use Mockito.whenbut prefer Mockito.doReturn(...).when, otherwise the method will be called once for real. If you consider the expression:

但需要注意的是:由于调用的是真正的方法,因此您不应使用Mockito.when而是更喜欢Mockito.doReturn(...).when,否则该方法将被真正调用一次。如果考虑表达式:

Mockito.when(myClass.methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class))).thenReturn(Collections.<X, Y> emptyMap());
             ^-----------------------------------^
                 this will be invoked by Java

the argument of the method whenmust be evaluated, but this means the method methodUsedInMethodBeingTestedwill be invoked. And since we have a spy, it is the real method that will be invoked. So, instead, use:

when必须评估方法的参数,但这意味着methodUsedInMethodBeingTested将调用该方法。并且由于我们有一个 spy,它是将被调用的真正方法。因此,请改用:

MyClass spy = Mockito.spy(new MyClass());
Mockito.doReturn(Collections.<X, Y> emptyMap()).when(spy).methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class));
assertNull(spy.methodToTest(myObject));
Mockito.verify(spy).methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class));

回答by Andy Turner

You are invoking the methodToTeston the mock instance. Because you have not configured it otherwise, that just returns null, it doesn't try to invoke any of the actual method's implementation.

您正在methodToTest模拟实例上调用。因为您没有以其他方式配置它,它只返回 null,它不会尝试调用任何实际方法的实现。