我和我的同事目前正在向我们的旧版 Java EE5 代码库引入单元测试。我们主要使用 JUnit 和 Mockito。在编写测试的过程中,我们注意到 EJB 中的几个方法很难测试,因为它们同时做了很多事情。
我对整个测试业务相当陌生,因此我正在寻找有关如何更好地构建代码或测试的见解。我的目标是编写好的测试而不会让人头疼。
这是我们的方法之一及其在管理消息队列的服务中的逻辑步骤的示例:
消费消息
确认先前下载的消息
获取NewUnreadMessages
addExtraMessages(取决于有些复杂的条件)
将消息标记为已下载
序列化消息对象
顶级方法当前在接口(interface)中公开,而所有子方法都是私有(private)的。据我了解,仅仅开始测试私有(private)方法是不好的做法,因为只有公共(public)接口(interface)才重要。
我的第一 react 是公开所有子方法并单独测试它们,然后在顶级方法中确保它调用子方法。但后来一位同事提到,将所有这些低级方法暴露在与另一个方法相同的级别可能不是一个好主意,因为这可能会引起困惑,并且其他开发人员可能会在应该使用顶级方法时开始使用一。我挑不出他的论点。
所以我来了。
您如何协调公开易于测试的低级方法与避免困惑的界面?在我们的例子中,是 EJB 接口(interface)。
我在其他单元测试问题中读到应该使用依赖注入(inject)或遵循单一职责原则,但我在实践中应用它时遇到了困难。有人能指导如何将这种模式应用到上面的示例方法吗?
您会推荐其他通用的 OO 模式或 Java EE 模式吗?
最佳答案
乍一看,我想说我们可能需要引入一个新类,它 1) 公开可以进行单元测试的公共(public)方法,但 2) 不会在 API 的公共(public)接口(interface)中公开。
举个例子,假设您正在为汽车设计 API。要实现 API,您需要一个引擎(具有复杂的行为)。您想要全面测试您的引擎,但您不想向汽车 API 的客户端公开详细信息(我对我的汽车的了解就是如何按下启动按钮以及如何切换 radio channel )。
在这种情况下,我会做类似的事情:
public class Engine {
public void doActionOnEngine() {}
public void doOtherActionOnEngine() {}
}
public class Car {
private Engine engine;
// the setter is used for dependency injection
public void setEngine(Engine engine) {
this.engine = engine;
}
// notice that there is no getter for engine
public void doActionOnCar() {
engine.doActionOnEngine();
}
public void doOtherActionOnCar() {
engine.doActionOnEngine();
engine.doOtherActionOnEngine(),
}
}
对于使用Car API的人来说,没有办法直接访问引擎,因此不存在造成伤害的风险。另一方面,可以对引擎进行全面的单元测试。
关于unit-testing - 如何重构和单元测试复杂的遗留 Java EE5 EJB 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12892524/