Mockito verify(...) 失败 - “实际上,与此模拟的交互为零。” 连续进行多次测试

Mic*_*hal 5 java testng mockito

我有一个 Wrapper 类,它会导致在包装对象上调用 equalsWithoutId 方法,而不是 equals 方法。此处实现:

import org.apache.commons.lang3.Validate;

public class IdAgnosticWrapper {

    private final IdAgnostic wrapped;

    public IdAgnosticWrapper(IdAgnostic wrapped) {
        Validate.notNull(wrapped, "wrapped must not be null");
        this.wrapped = wrapped;
    }

    @Override
    public int hashCode() {
        return wrapped.hashCodeWithoutId();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof IdAgnosticWrapper)) {
            return false;
        }
        return wrapped.equalsWithoutId(((IdAgnosticWrapper) obj).getWrapped());
    }

    public IdAgnostic getWrapped() {
        return wrapped;
    }
}
Run Code Online (Sandbox Code Playgroud)

IdAgnostic 是一个简单的接口,可确保存在所需的方法

public interface IdAgnostic {
    int hashCodeWithoutId();
    boolean equalsWithoutId(Object o);
}
Run Code Online (Sandbox Code Playgroud)

然后我有一些单元测试应该测试 equals() 委托给wrapped#equalsWithoutId() 方法和 hashCode() 委托给wrapped#hashCodeWithoutId。

现在我尝试通过这些测试来测试它

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.mockito.Mockito.verify;

public class IdAgnosticWrapperTest {

    @Mock
    private IdAgnostic wrappedMock;

    @InjectMocks
    private IdAgnosticWrapper tested;


    @BeforeMethod
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testEquals_EqualsWithoutIdIsCalledOnWrapped() throws Exception {
        tested.equals(tested);
        verify(wrappedMock).equalsWithoutId(tested.getWrapped());
    }

    @Test
    public void testHashCode_HashCodeWithoutIdIsCalledOnWrapped() throws Exception {
        tested.hashCode();
        verify(wrappedMock).hashCodeWithoutId(); //line 34
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我只是创建了包装的模拟并测试了 equals 和 hashcode 是否委托了功能。

如果我单独运行测试,一切正常,但如果我按顺序运行两个测试,第二个测试将失败并显示此消息

Wanted but not invoked:
wrappedMock.hashCodeWithoutId();
-> at com.my.app.utils.IdAgnosticWrapperTest.testHashCode_HashCodeWithoutIdIsCalledOnWrapped(IdAgnosticWrapperTest.java:34)
Actually, there were zero interactions with this mock.
Run Code Online (Sandbox Code Playgroud)

为什么会出现这种情况?

ent*_*erd 3

Effectively, what's happening here is that the @InjectMocks isn't able to correctly inject the constructor parameter wrapped. According to the Javadoc for @InjectMocks, this is the current behavior. So unless you want to use setter injection, you will need to remove the @InjectMocks annotation. See the revised code:

public class IdAgnosticWrapperTest {

  @Mock
  private IdAgnostic wrappedMock;

  private IdAgnosticWrapper tested;

  @BeforeMethod
  public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);

    this.tested = new IdAgnosticWrapper(this.wrappedMock);
  }

  @Test
  public void testEquals_EqualsWithoutIdIsCalledOnWrapped()
      throws Exception {
    tested.equals(tested);
    verify(wrappedMock).equalsWithoutId(tested.getWrapped());
  }

  @Test
  public void testHashCode_HashCodeWithoutIdIsCalledOnWrapped()
      throws Exception {
    tested.hashCode();
    verify(wrappedMock).hashCodeWithoutId(); //line 34
  }
}
Run Code Online (Sandbox Code Playgroud)

When I ran the above code, both tests ran together sequentially and passed.

  • `@InjectMocks` 并不*模拟它所注释的字段中的对象,而是允许 Mockito 将 `@Mock` 和 `@Spy` 字段中的模拟反射性地安装/注入到 `@InjectMock`ed 对象的构造函数和字段中。也就是说,您对“@InjectMocks”是一个问题的看法是正确的,因为 TestNG 重用了测试对象,并且由于字段的最终修饰符,Mockito 无法现场注入 IdAgnosticWrapper。查看更多信息[此处](http://stackoverflow.com/questions/20046210/mockito-injectmocks-strange-behaviour-with-final-fields)。 (2认同)
  • 感谢您提供的解决方案,但问题并不在于事实上,包装的字段是最终的。问题是,MockitoAnnotations.initMocks(this); 创建了私有 IdAgnosticwrappedMock 的新实例;,​​但没有创建经过测试的私有 IdAgnosticWrapper 的新实例;因此,我验证了在对象上调用了方法,该方法从未被包装器包装过(有之前测试中的实例)。这个问题似乎是http://stackoverflow.com/questions/20046210/mockito-injectmocks-strange-behaviour-with-final-fields的重复 (2认同)