jMockit - 如何使对 return 的构造函数调用成为模拟

jMockit - How make constructor invocation to return a mock

我们目前使用 Mockito + PowerMock 作为我们的主要模拟框架,并且在开始将我们的一些代码移至 java 8 后遇到了一些问题。 因此,我们决定评估 jMockit 作为替代方案。我对模拟概念有很好的理解,但我承认我对 jMockit 的经验非常有限。

然而,我在测试一些在我看来应该是非常基本的东西时遇到了问题:被测试的 class 在其构造函数中使用 new 创建了其他 class 的实例。那个新的调用是我想让 return 成为一个模拟实例的东西。

这是我正在使用的代码: 包裹 com.some.org.some.app;

import mockit.Expectations;
import mockit.Injectable;
import mockit.Mocked;
import org.testng.annotations.Test;

public class ClassUnderTestTest {
    interface SomeService {
        void doWork();
    }

    class ClassUnderTest {
        private final SomeService service;

        public ClassUnderTest() {
            this.service = new SomeService() {
                @Override
                public void doWork() {
                }
            };
        }
    }

    @Injectable
    private SomeService mockService;

    @Test
    public void shouldBeAbleToMaskVariousNumbers() throws Exception {
        new Expectations() {{
            new ClassUnderTest();
            result = mockService;
        }};
    }
}

当 运行 以上时,我得到以下异常:

java.lang.IllegalStateException: Missing invocation to mocked type at this point;
please make sure such invocations appear only after the declaration of a suitable
mock field or parameter

我使用 TestNG 作为测试框架,实际上我的测试方法有一堆参数,因为它期望数据提供者传递一些测试数据。

这是非常基本的,看起来我的方法不是 jMockit 方式。预先感谢您的支持。

使用 JMockit 很容易做到这一点:

public class ClassUnderTestTest {
    interface SomeService { int doWork(); }

    class ClassUnderTest {
        private final SomeService service;

        ClassUnderTest() {
            service = new SomeService() {
                @Override public int doWork() { return -1; }
            };
        }

        int useTheService() { return service.doWork(); }
    }

    // This annotation is a variation on @Mocked, which extends
    // mocking to any implementation classes or subclasses of
    // the mocked base type.
    @Capturing SomeService mockService;

    @Test
    public void shouldBeAbleToMaskVariousNumbers() {
        new Expectations() {{ mockService.doWork(); result = 123; }};

        int n = new ClassUnderTest().useTheService();

        assertEquals(123, n);
    }
}