Mockito verify(...) 失败 - "Actually, there were zero interactions with this mock." 在多个测试中依次 运行
Mockito verify(...) fails - "Actually, there were zero interactions with this mock." in more than one test run sequentially
我有一个 Wrapper class 导致在包装对象上调用 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;
}
}
IdAgnostic 是一个简单的接口,可确保存在所需的方法
public interface IdAgnostic {
int hashCodeWithoutId();
boolean equalsWithoutId(Object o);
}
然后我有一些应该测试的单元测试,如果 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
}
}
如您所见,我只是创建了包装模拟并测试了 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.
为什么会这样?
实际上,这里发生的是 @InjectMocks
无法正确注入构造函数参数 wrapped
。根据 Javadoc for @InjectMocks
,这是当前的行为。所以除非你想使用 setter 注入,否则你需要删除 @InjectMocks
注释。查看修改后的代码:
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
}
}
当我运行以上代码时,两个测试运行一起按顺序通过。
我有一个 Wrapper class 导致在包装对象上调用 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;
}
}
IdAgnostic 是一个简单的接口,可确保存在所需的方法
public interface IdAgnostic {
int hashCodeWithoutId();
boolean equalsWithoutId(Object o);
}
然后我有一些应该测试的单元测试,如果 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
}
}
如您所见,我只是创建了包装模拟并测试了 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.
为什么会这样?
实际上,这里发生的是 @InjectMocks
无法正确注入构造函数参数 wrapped
。根据 Javadoc for @InjectMocks
,这是当前的行为。所以除非你想使用 setter 注入,否则你需要删除 @InjectMocks
注释。查看修改后的代码:
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
}
}
当我运行以上代码时,两个测试运行一起按顺序通过。