【问题标题】:jMockit - How make constructor invocation to return a mockjMockit - 如何使构造函数调用返回一个模拟
【发布时间】:2015-03-11 06:32:51
【问题描述】:

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

但是,我在测试一些在我看来应该是非常基本的东西时遇到了问题:被测类使用 new 在其构造函数中创建了某个其他类的实例。这个新的调用是我想要返回一个模拟实例的东西。

这是我正在使用的代码: 包 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 方式。提前感谢您的支持。

【问题讨论】:

    标签: java mocking testng jmockit


    【解决方案1】:

    使用 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);
        }
    }
    

    【讨论】:

    • 这确实很容易。非常感谢您的意见。我还学习了 Capturing 注释的正确用法。当我阅读教程时,我一开始并没有太在意这个,因为我认为它可能用于捕获方法参数等调用数据。在我看来我需要另一个,这次更仔细,阅读 jMockit 教程。至于我得到的异常,我的愚蠢错误是我对 ClassUnderTest 构造函数设置了期望,这显然是错误的。
    猜你喜欢
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2016-12-31
    • 2021-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多