计数间接方法调用Mockito



我有计数方法调用与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)

有什么想法吗?提前感谢!

可以。使用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++;
        }
    }

这表明您需要进行一些重构来改进您的设计。单个类应该是完全可测试的,而不需要模拟出它的一部分。您认为需要模拟的任何部分都应该提取到一个或多个协作对象中。不要落入部分模拟的陷阱。听听测试告诉你什么。未来的自己会感谢你的。

您正在模拟被测试的类。mock用于测试类的依赖关系,而不是类本身。

我怀疑你要的是Mockito.spy()。但是,这是Mockito Javadoc建议反对的部分mock

或者,如果您想为可测试性而重构,您可以这样做:

@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;
    }
}

相关内容

  • 没有找到相关文章

最新更新