统计 Mockito 的间接方法调用

发布于 2024-12-11 04:40:22 字数 1132 浏览 0 评论 0原文

我在使用 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)

请有任何想法。提前致谢!

I'm having problems with counting method calls with Mockito. Problem is that the method whos calls I want to count is called in test class indirectly by other method. Here is the code:

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

And the test class:

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

Having such exception:

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)

Any ideas please. Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

妄断弥空 2024-12-18 04:40:22

这会起作用。使用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++;
        }
    }

This will work. Using a spy calls the underlying method. Make sure value is initialized first.

    @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++;
        }
    }
瞎闹 2024-12-18 04:40:22

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

This is an indication that you need some refactoring to improve your design. A single class should be fully testable without needing to mock out pieces of it. Whatever pieces you feel need to be mocked out should be extracted into one or more collaborating objects. Don't fall into the trap of partial mocks. Listen to what the tests are telling you. Your future self will thank you.

旧伤慢歌 2024-12-18 04:40:22

你在嘲笑被测试的班级。模拟旨在针对已测试类的依赖项,而不是类本身。

我怀疑你想要的是Mockito.spy()。然而,这是 Mockito Javadoc 建议反对的部分模拟

You are mocking the tested class. Mocking is intended for the dependencies of a tested class, rather than the class itself.

I suspect what you want is Mockito.spy(). However, this is partial mocking which the Mockito Javadoc recommends against.

陈甜 2024-12-18 04:40:22

或者,如果您想重构可测试性,您可以执行以下操作:

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

Alternatively, if you want to refactor for testability, you can do the following:

@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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文