【问题标题】:How do I mock objects in a Java class that has no (non-default) constructor?如何在没有(非默认)构造函数的 Java 类中模拟对象?
【发布时间】:2016-01-15 15:06:55
【问题描述】:

我正在为遗留的 Tomcat Web 服务设置第一个单元测试,该服务没有考虑到测试,也没有使用 Spring。我遇到问题的类之一是扩展 HttpServlet 的 servlet。这是该类的缩写版本。

public class ItemServlet extends HttpServlet {
    private ObjectMapper mapper;
    private IItemDAO dao;

    @Override
    public void init() {
        mapper = new ObjectMapper();
        dao = new GenericItemDao(...);
    }
}

通常我会将外部依赖项传递给构造函数,但 Tomcat 基于 web.xml 配置创建 servlet,它只调用默认构造函数和无参数的 init() 方法。结果,似乎没有任何方法可以进行依赖注入以允许我在单元测试中进行模拟。我能想到的唯一方法是创建一个仅用于测试的构造函数,我可以使用它从我的单元测试中实例化类,并将 init() 方法保留为实际应用程序调用的方式。我还可以创建第三个方法,可以由构造函数和init() 调用,如下所示:

public class ItemServlet extends HttpServlet {
    private ObjectMapper mapper;
    private IItemDAO dao;

    public ItemServlet(ObjectMapper mapper, IItemDAO dao) {
        initDependencies(mapper, dao);
    }

    private void initDependencies(ObjectMapper mapper, IItemDAO dao) {
        this.mapper = mapper;
        this.dao = dao;
    }

    @Override
    public void init() {
        initDependencies(new ObjectMapper(), new GenericItemDAO(...));
    }
}

有没有更简洁的方法对这些类进行单元测试?

【问题讨论】:

  • 如果你可以使用PowerMockito框架,你可以模拟ObjectMapperItemDAO类的构造函数。请参阅示例here。希望这会有所帮助

标签: java unit-testing tomcat mocking


【解决方案1】:

我会利用这个机会解耦代码并使其可测试。事实上,如果您代表 Tomcat 实例化一个 servlet,只是为了检查其中一个方法是否返回预期值,那么您就已经超出了单元测试的范围,而是在进行集成测试。

使用 Mock 框架来解决这个问题将使当前的实现变得一成不变,并且无法更改 - 除非这些更改与测试的更改一起发生。

我是单元测试的绝对支持者,并且我也是一个实用主义者,如果我发现自己处于难以测试的几个框架层中,我会尽其所能。在这种情况下(我只知道您的 servlet 依赖项,而不知道任何其他依赖项 - 您会知道自己在哪里)我喜欢将我的代码分成

  • 原子的、可单元测试的单元,没有框架依赖项
  • 连接代码,将可测试代码与框架连接起来。

接线代码自然不是很复杂,也没有经过任何测试(由于大量的依赖关系)。不过,它得到了同行评审。

【讨论】:

  • 我实际上并没有测试任何 servlet 功能,但实际上是方法中的业务逻辑(doPost、doGet 等)。但是,您提出了一个很好的观点,如果我将所有实际逻辑委托给另一个类(例如,ItemRequestHandler),那么我可以对其进行完全单元测试,并且只留下未测试的骨架 servlet 类。这正是我在另一个项目(NodeJS)中使用的技术,我认为这是要走的路。
【解决方案2】:

您可以将getters/setters 添加到类中,并通过那里将mocks 注入到类中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2015-07-05
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多