【问题标题】:Partial Mocks for DI?DI 的部分模拟?
【发布时间】:2013-05-08 23:35:19
【问题描述】:

对于我上一个 Java 项目,我对所有类进行了单元测试。每个类都有自己的接口和实现(即 Person 和 PersonImpl)。类仅通过接口相互交互,我使用模拟来独立于其他类测试每个类。它最终真的很痛苦,因为它破坏了我的 eclipse ctrl+click 导航,因为每个方法调用都是在接口上调用的。它还使业务代码有点混乱,每次我创建一个对象时都必须创建和传递依赖工厂,而该对象创建它的依赖关系完全没问题(除了测试之外)。我偶然发现了另一种形式的依赖注入,它似乎为我解决了这两个问题,我想知道是否有人可以告诉我为什么这不是一个好主意。

这是一个简单的、人为的非现实示例...假设 File 和 FileFactory 是接口。

基于接口的构造函数 DI

public class Logger {

    private File file;

    public Logger(FileFactory fileFactory, String fileName) {
        file = fileFactory.create(fileName);
        file.createNewFile();
    }

    public void debug(String message) {
        file.append("[debug] " + message);
    }

    public void error(String message) {
        file.append("[error] " + message);
    }
}

部分模拟依赖注入

public class Logger {

    private File file;

    public Logger(String fileName) {
        file = createFile(fileName);
        file.createNewFile();
    }

    public void debug(String message) {
        file.append("[debug] " + message);
    }

    public void error(String message) {
        file.append("[error] " + message);
    }

    public File createFile(String fileName) {
        return new File(fileName);
    }
}

在第二个例子中,没有接口或工厂,类之间的关系被保留,所以我可以 ctrl+click 到“createNewFile()”或“append”。在编写测试时,我可以使用 Mockito 对此类进行部分模拟,并指示它为“createFile(String)”返回一个模拟文件,因此我仍然可以在测试期间注入依赖项。我看到这样做的好处。有什么我没有看到的缺点吗?

【问题讨论】:

    标签: java unit-testing dependency-injection mocking mockito


    【解决方案1】:

    我对 java 不太了解,但我知道 C# 中的 DI,所以我想我可以提供一些帮助。

    首先,请阅读此stackoverflow question。我已经问过要测试什么以及为什么要进行模拟。希望这个问题可以给出进行单元测试的大致思路。

    对我来说,模拟对象应该做什么:

    1. 简单

      简单的模拟对象可以使您的测试单元更容易审查。简单的模拟对象可以使它变得微不足道,并且不需要对模拟对象进行任何测试。一个简单的模拟对象将支持下面的第 4 点。

    2. 有最小的依赖

      在您的情况下,您对 FileFactory 的依赖较少。这很好,因为它更容易设置测试。具有最小依赖性的另一个好处是它具有最小的测试范围。它也将支持下面的第 4 点。

    3. 界面没有其他功能

      在您的示例中,您还有另一个函数public File createFile。我想知道它是否会被消费者使用(它是公开的)。恕我直言,最好将其设为私有以确保单元测试不会调用附加方法。

    4. 更改测试类时不会破坏测试类

      mock 对象最重要的一点是当测试类(消费者)发生变化时,mock 对象不会出错。因为要对测试类进行单元测试,所以任何错误都应该只由测试类引起。当错误是由模拟对象引起的时,将更难跟踪。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多