java - 如何测试/模拟这个静态工厂(用于图形构建)?

标签 java unit-testing junit mocking

所以,我已经实现了我的业务类,我通过构造函数传入所有依赖项,因此我可以模拟它们并轻松地对它们进行单元测试。到目前为止效果很好,但是有一次,我需要从这些对象中创建一个对象图。为此,我使用了一个静态工厂(遗憾的是我不能使用 DI 框架)。示例:

public class FooBar {
    public FooBar(Foo foo, Bar bar) {
        this.foo = foo;
        this.bar = bar;
    }
}

public class Foo  {
    public Foo() {}
}

public class Bar {
    public Bar(Foo foo) {
        this.foo = foo;
    }
}

public class GraphFactory {
    public static FooBar newFooBar() {
        Foo foo = new Foo();
        Bar bar = new Bar(foo);

        return new FooBar(foo, bar);
    }
}

因此,我无法真正测试 GraphFactory(无法模拟依赖项),这还算可以(这里没有做太多工作)。但是,如果图的构建更加复杂,即它涉及查找某些属性、进行 JNDI 查找等,该怎么办?

我还不应该为此编写单元测试吗?我的类(class)设计可能坏了吗?单元测试的目的不就是孤立地测试类吗?

最佳答案

这个设计没有任何问题,而且是完全可测试的。如果我们关注工厂的单一职责——它负责组装对象图——对此的测试是直截了当的:

  1. 根据先决条件设置工厂。
  2. 调用工厂方法。
  3. 断言该对象是按照您的要求构造的:已设置默认值等。

上面的例子中,foo、bar、foobar是测试的结果,不需要mock。

如果对象图的组装更复杂,并且您需要额外的服务来获取数据和检查应用程序设置,猜猜会发生什么?这些依赖项通过其构造函数传递到工厂中。您应该模拟这些依赖项以将工厂与其依赖项的依赖项隔离开来。您工厂的消费者将通过他们的构造函数接收一个完全连线的工厂;或者工厂在应用程序启动时组装并作为单例提供,等等。

这就是 DI 的工作原理。这听起来很奇怪,因为现在你必须担心工厂是如何创建的(以及谁创建了那个对象,等等,一直向下乌龟),这是一个完全自然的 react 。

这就是为什么我们有 DI 框架来组装复杂的对象图。在一个设计良好的 DI 应用程序中,没有人应该知道图形是如何组装的。类似于这种设计,DI 框架应该一无所知。

该规则的唯一异常(exception)是...(鼓声)...工厂对象!

如果要解析的对象在其构造函数中采用 DI,则大多数 DI 框架会将 DI 容器注入(inject)到对象中。这极大地简化了工厂的管道,并满足我们的设计原则:除了我们的工厂,没有人知道如何构造我们的对象,我们已经将 DI 容器的知识封装到应用程序的负责对象组装的关键区域。

哇哦。现在,如果您仍在继续,这将如何改变我们的测试?它不应该,至少不要太多:步骤 #1 略有变化,您用模拟对象填充 DI 容器,然后使用 DI 容器构建工厂。

作为一种品味,有些人喜欢在测试期间使用自动模拟 DI 容器,在请求项目时自动生成模拟依赖项。这可以消除大部分设置难题。

关于java - 如何测试/模拟这个静态工厂(用于图形构建)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9290584/

相关文章:

java - 流式传输直到找到值 - 可选

java - onClickListener 不工作

reactjs - 如何通过更改 useState 来测试 React Hooks 组件

java - 从哪里开始编写单元测试

unit-testing - AbstractTransactionalJUnit4SpringContextTests : can't get the dao to find inserted data

java - 登录 JUnit 测试用例

java - Richfaces a4j :commandButton not working when enabled after a ajax response

java - 在不同远程对象之间拆分远程 EJB 功能

c# - 如何根据 Moq 方法设置中的参数值返回两个不同的值?

java - 如何使用 JUnit 和 Maven Surefire 插件将数据添加到测试用例