Mockito:通缉但未调用

2022-01-14 00:00:00 unit-testing mockito java

我有如下测试方法:

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

methodUsedInMethodBeingTested 是一种我想模拟并返回空映射的方法.但我收到失败消息说

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

需要但未调用 myClass.methodUsedInMethodBeingTested()

Wanted but not invoked myClass.methodUsedInMethodBeingTested()

.

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

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

推荐答案

你误解了什么是 mock.当你在做的时候

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

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

您实际上并没有在您的真实对象上调用 methodToTest.您正在模拟上调用 methodToTest,默认情况下,它什么也不做并返回 null,除非它被存根.引用 Mockito 文档:

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:

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

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, ...).

这解释了您随后的错误:该方法实际上没有在模拟上调用.

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

看来你想要的是 spy 改为:

It seems what you want here is a spy instead:

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

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

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

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(myClass.methodUsedInMethodBeingTested(Matchers.any(MyTypeParam.class))).thenReturn(Collections.<X, Y> emptyMap());
             ^-----------------------------------^
                 this will be invoked by Java

方法 when 的参数必须被计算,但这意味着方法 methodUsedInMethodBeingTested 将被调用.因为我们有一个间谍,所以它是真正的方法将被调用.所以,改为使用:

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:

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

相关文章