我多年来一直是 EasyMock 的粉丝,多亏了 SO,我发现了对 PowerMock 的引用以及它模拟构造函数和静态方法的能力,这两者都会在对遗留代码库进行改造测试时引起问题。
显然,单元测试(和 TDD)的巨大好处之一是它导致(强制?)更简洁的设计,在我看来,PowerMock 的引入可能会损害这一点。我认为这主要表现为:
- 回到初始化合作者而不是注入(inject)他们
- 使用静态而不是让方法归合作者所有
除此之外,关于我的代码为测试而被操纵的字节码,我有些不太对劲。我真的不能给出一个具体的原因,只是这让我感到有点不安,因为它只是为了测试而不是为了生产。
在我目前的工作中,我们真正插入单元测试作为人们改进编码实践的一种方式,感觉将 PowerMock 引入等式可能会让人们稍微跳过这一步,所以我不愿意开始使用它。话虽如此,我确实可以看出在哪些方面使用它可以减少开始测试类所需的重构量。
我想我的问题是,人们使用 PowerMock(或任何其他类似库)来实现这些功能的体验如何?您会使用它们吗?您希望您的测试对您的设计产生多大的影响?
我不得不强烈反对这个问题。
没有理由限制设计选择的模拟工具。 EasyMock、EasyMock 类扩展、jMock、Mockito 和其他方法排除的不仅仅是静态方法。这些工具还阻止您将类和方法声明为 final
,仅此一项就非常糟糕。 (如果您需要一个为类和方法使用 final
辩护的权威来源,请参阅“Effective Java”一书,或观看作者的 presentation。)
根据我的经验,“初始化协作者而不是注入(inject)他们”通常是最好的设计。如果通过创建从该类实例化的辅助类来分解解决某些复杂问题的类,则可以利用将特定数据安全地传递给这些子对象的能力,同时将它们隐藏在客户端代码之外(这提供了高级操作中使用的完整数据)。在公共(public) API 中公开此类辅助类违反了信息隐藏原则,破坏了封装并增加了客户端代码的复杂性。
滥用 DI 会导致无状态对象,而这些对象实际上应该是有状态的,因为它们几乎总是对特定于业务操作的数据进行操作。
这不仅适用于非公共(public)帮助类,也适用于从 UI/表示对象调用的公共(public)“业务服务”类。此类服务类通常是内部代码(针对单个业务应用程序),本质上不可重用,并且只有几个客户端(通常只有一个),因为此类代码本质上是特定领域/用例。
在这种情况下(顺便说一下,这是一种非常常见的情况),让 UI 类直接实例化业务服务类并通过构造函数传递用户提供的数据更有意义。
能够轻松地为这样的代码编写单元测试正是促使我创建 JMockit 的原因工具包。我考虑的不是遗留代码,而是设计的简单性和经济性。到目前为止,我取得的结果使我确信,可测试性 确实是两个变量的函数:生产代码的可维护性,以及用于测试该代码的模拟工具的局限性.那么,如果您从模拟工具中移除所有限制,您会得到什么?