如何在不修改生产代码的情况下打破依赖关系?
Posted
技术标签:
【中文标题】如何在不修改生产代码的情况下打破依赖关系?【英文标题】:How to break dependencies without modifying production code? 【发布时间】:2009-06-17 14:49:04 【问题描述】:根据我对单元测试的初步阅读(我是初学者),将所有设置和测试与正在测试的代码放在一个单独的项目中是明智的。这对我来说似乎也很理想。然而,我最近开始阅读单元测试的艺术,试图发现如何打破对数据库调用等事物的依赖关系。提供的方法涉及更改测试代码的区域,例如向生产代码添加特定接口和“存根”方法。这似乎破坏了将测试和生产代码分开的一些好处。
是否有任何推荐的不涉及更改生产代码的依赖关系破坏技术?
【问题讨论】:
一开始就正确编写代码(例如,使用依赖注入方法)。如果您首先对依赖项进行硬编码,则没有好的 方法可以稍后在不更改代码的情况下删除它们,只有肮脏的黑客攻击。测试将保持独立,但生产代码必须是可测试的!-) 【参考方案1】:如果不进行某种更改,就无法打破依赖关系。重要的是,您所做的更改不会改变生产代码在生产环境中的行为,并且不会引入更糟糕的依赖关系。
【讨论】:
【参考方案2】:根据定义,需要在生产代码中打破依赖关系以使其更具可测试性,即,要使生产代码更具可测试性,您需要更改代码以使其与实际实现的耦合度降低。这将允许您在测试中用模拟对象替换被测类中的真实对象。这消除了对被测类所依赖的其他生产类的依赖。
如果您编写了松散耦合的生产代码(依赖于接口而不是实现的代码,使用工厂和依赖注入来创建对象而不是直接实例化的代码),那么您可能只需要进行少量更改或无需进行任何更改完全到您的生产代码。如果没有,那么您将需要进行这些类型的更改。然而,这并不是一件坏事,因为它将通过减少类之间的耦合来改进您的设计。这样做的代价是一些额外的(小)类和/或使隔离成为可能的接口。
如果您使用 TDD(测试驱动开发/设计),您在生产代码中使用的构造类型将发生变化,以使其更自然地可测试。这是 TDD 用于改进设计以及将测试合并到代码中的方法之一。
请注意,您不需要将生产代码中的耦合或依赖项引入测试代码。您的测试代码显然将依赖于生产环境,您可能需要重构生产环境中的依赖关系以使其更具可测试性,但如果您的生产代码“知道”任何关于它如何被测试的信息,那么您可能做错了什么。当您应该使用依赖注入时,您可能已经引入了人工接口。
【讨论】:
【参考方案3】:我们使用 Spring 和工厂来打破依赖关系。使用 Spring 的依赖注入,从开发和测试到生产只是一个不同的 XML 文件。
【讨论】:
以上是关于如何在不修改生产代码的情况下打破依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章