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
Mockito: Wanted but not invoked
提问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 methodUsedInMethodBeingTested
is 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 methodToTest
on your real object. You're invoking methodToTest
on 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 spy
instead:
看来你想要的是一个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.when
but 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 when
must be evaluated, but this means the method methodUsedInMethodBeingTested
will 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 methodToTest
on 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,它不会尝试调用任何实际方法的实现。