我在使用Mockito计算方法调用时遇到问题。问题是我想要计数的调用方法是在测试类中通过其他方法间接调用的。这是代码:
public class ClassForTest {
private Integer value;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
测试类:
public class ClassForTestTest extends TestCase {
@Test
public void testDoSmth() {
ClassForTest testMock = mock(ClassForTest.class);
doNothing().when(testMock).prepareValue(anyString());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
}
有这样的例外:
Wanted but not invoked:
classForTest.prepareValue(<any>);
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:24)
However, there were other interactions with this mock:
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:21)
请任何想法。提前谢谢!
答案 0 :(得分:10)
这会奏效。使用spy
调用基础方法。确保首先初始化value
。
@Test
public void testDoSmth() {
ClassForTest testMock = spy(new ClassForTest());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private Integer value = 0;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
答案 1 :(得分:5)
这表明您需要进行一些重构来改进您的设计。单个类应该是完全可测试的,而不需要模拟它的部分。无论你认为需要被嘲笑的任何作品都应该被提取到一个或多个合作对象中。 不要陷入部分嘲笑的陷阱。听听测试告诉你的内容。你未来的自我会感谢你。
答案 2 :(得分:1)
你在嘲笑被测试的班级。模拟用于测试类的依赖关系,而不是类本身。
我怀疑你想要的是Mockito.spy()
。但是,这是Mockito Javadoc建议反对的部分模拟。
答案 3 :(得分:1)
或者,如果要重构可测试性,可以执行以下操作:
@Test
public void testDoSmth() {
Preparer preparer = mock(Preparer.class);
ClassForTest cft = new ClassForTest(preparer);
cft.doSmth();
verify(preparer, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private final Preparer preparer;
public ClassForTest(Preparer preparer) {
this.preparer = preparer;
}
public void doSmth() {
preparer.prepareValue("First call");
preparer.prepareValue("Second call");
preparer.prepareValue("Third call");
System.out.println(preparer.getValue());
}
}
public class Preparer {
private Integer value = 0;
public void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
public Integer getValue() {
return value;
}
}