【问题标题】:How to inject mocked dependencies with jmockit如何使用 jmockit 注入模拟依赖项
【发布时间】:2014-11-05 13:46:17
【问题描述】:

目前我试图了解@Injectable@Tested 注释是如何工作的。我已经做了一些测试并理解了这个概念,但我不知道如何在现实世界的应用程序中使用这些注释。

假设我们正在开发一个依赖于 Web 服务的语言翻译器类。 Web 服务方法被封装在一个单独的类中:

// class to test
public class Translator() {
    private TranslatorWebService webService;

    public String translateEnglishToGerman(String word){
        webService = new TranslatorWebService();
        return webService.performTranslation(word);
    }
}

// dependency
public class TranslatorWebService {
    public String performTranslation(String word){
    // perform API calls    
    return "German Translation";
    }
}

为了独立测试Translator 类,我们想模拟TranslatorWebService 类。根据我的理解,测试类应该是这样的:

public class TranslatorTest {
    @Tested private Translator tested;
    @Injectable private TranslatorWebService transWebServiceDependency;

    @Test public void translateEnglishToGerman() {
        new Expectations() {{
            transWebServiceDependency.performTranslation("House");
            result = "Haus";
        }};

        System.out.println(tested.translateEnglishToGerman("House"));
    }
}

当我第一次执行这个测试用例时,我期望结果是“Haus”。乍一看,我看到了这条线

webService = new TranslatorWebService();

将始终用真实实例覆盖注入的模拟实例。但是如何在不改变业务逻辑的情况下避免这种行为呢?

【问题讨论】:

    标签: java mocking jmockit


    【解决方案1】:

    好问题。关于 JMockit(或任何其他模拟 API)对依赖注入的支持需要注意的是,它仅在被测代码实际上依赖于其依赖注入时才使用。

    示例Translator 类确实 依赖于TranslatorWebService 依赖项的注入;而是直接通过内部实例化获得。

    因此,在这种情况下,您可以简单地模拟依赖项:

    public class TranslatorTest {
        @Tested Translator tested;
        @Mocked TranslatorWebService transWebServiceDependency;
    
        @Test public void translateEnglishToGerman() {
            new Expectations() {{
                transWebServiceDependency.performTranslation("House");
                result = "Haus";
            }};
    
            String translated = tested.translateEnglishToGerman("House");
    
            assertEquals("Haus", translated);
        }
    }
    

    【讨论】:

    • 感谢您的回答。我不知道@Mocked 对象也会被注入。根据文档,只有 @Injectable 对象支持此功能:For injection to be performed, the test class must also contain one or more mock fields or mock parameters declared to be @Injectable. Mock fields/parameters annotated only with @Mocked or @Capturing are not considered for injection.(官方文档:jmockit.github.io/tutorial/BehaviorBasedTesting.html#tested)但无论如何,这个解决方案对我有用。非常感谢!
    • @Mocked 对象注入;他们的课程被嘲笑了。
    • 只是想指出,在这种情况下,通过设置 Web 服务返回“Haus”的期望并断言测试对象返回“Haus”,我们确实没有取得太大的成就。测试。关于使用@Mocked 的答案是正确的,但对我来说,确保我们真正实现一些有用的测试似乎更重要,所以我建议重组测试主题将测试更改为仅验证测试对象是否使用预期参数调用 Web 服务。
    • @unigeek 确实如此。测试应该只是验证performTranslation("House") 被调用了,仅此而已;使用 JMockit API,这将转化为用期望 verification 块替换期望记录块:new Verifications() {{ transWebServiceDependency.performTranslation("House"); }};
    猜你喜欢
    • 2022-11-26
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 2021-05-15
    • 2020-04-14
    相关资源
    最近更新 更多