接口如何使单元测试和模拟更容易?

时间:2010-03-03 09:55:41

标签: unit-testing mocking

通常说接口使得模拟和单元测试变得更容易。接口如何帮助解决这个问题?

5 个答案:

答案 0 :(得分:6)

接口的本质是提供许多实现,从而实现模拟

特别是在集成测试中,您可以提供依赖系统模型的版本(例如Web服务)。 您可以提供最简单的界面实现,而不是实际调用依赖系统甚至模块,或复杂且难以实例化类型将提供所需的结果,以便正确完成单元测试

除此之外,当你在单元测试中使用时,实际的依赖类型(称之为BigGraph)隐藏了一个复杂的对象模型,你实际上是集成测试不是单元测试。 如果任何依赖类型(BigGraph)中存在错误,您的测试很容易中断,而不是您正在测试的类型,因此不是单元测试。使用模型可以降低发生的风险。

我已经看到很多持续集成系统显示一个错误的几十个错误,当它们应该显示一个,或者最多一个,都是因为太复杂的对象模型和错误编写的单元测试 - 不使用mock -UPS。

今天,模拟框架比过去更复杂(字节码修改等),所以有时候并不总是需要接口甚至虚拟方法,但是无神经接口使它们成为可能。

如果您的对象模型过于复杂和混乱

接口无法帮助(例如,您的界面严重依赖其他类型/接口);那么实施/嘲笑这一切都是一种痛苦

答案 1 :(得分:5)

如果你有一个类,你可以有很多依赖,比如

  • 疯狂构造函数(许多参数,或者它需要一些其他类需要第三个类,需要第四个类需要有效的数据库连接)

  • 要以任何方式使用该类,必须正确初始化它(例如,您必须将其它一些必须有效的对象传递给它)

  • 班级有州。由于某种原因,这种状态可能会在测试期间发生变化。

  • 该类可能具有或使用静态字段

这些依赖项通常在您的许多测试中都无关紧要,您宁愿不必处理它们。

使用接口,您可以创建一个简单的模拟类,它只实现您需要的几个方法。大多数模拟框架都内置了对此的支持。这里的“实施”通常意味着“返回固定价值”。这样,您就可以快速构建被测试类所需的环境。

因此,例如,如果您的类需要从数据库中读取记录,则可以模拟仅返回行的ResultSet。因此,您不必拥有真正的数据库,您不需要创建连接(这很慢并且可能由于多种原因而失败),您不必关心数据库中的数据(所以你不要不必删除/删除表并再次使用测试数据填充它们等等。

答案 2 :(得分:4)

如果有多个对象具有不同的实现但向外部提供相同的方法共享相同的接口,则可以编写一个单元测试并针对所有实现运行它。

如果你有一个课程说明将内容发布到网络后端,然后检索一个有问题的答案单元测试,因为失败的互联网连接可能会让你的测试失败。因此,您为此类定义了一个接口,然后您可以编写第二个实现,记录应该发送的内容并提供正确的答案。这样,您可以在测试运行时测试使用后端答案的类,而不依赖于Internet连接。

答案 3 :(得分:2)

如果您不受具体实现的约束,可以在界面后面切换行为。

如果您的类实现接口,则可以模拟行为。

例如,您无需向数据库中的所有客户发送垃圾邮件,以测试您的邮件通知算法是否有效。您将为IMailSender界面创建模拟,并仅计算发送的电子邮件数。然后,您将测试实际在单个电子邮件地址上发送电子邮件的实际实施,并且您知道整个通知过程有效。

在此特定示例中,测试使用模拟实现IMailSender,仅计算发送的电子邮件,您的实际生产代码将使用实现IMailSender实现通过SMTP服务器实际发送电子邮件的实现。< / p>

答案 4 :(得分:0)

当测试穿过端口的行为时,为适配器提供接口将有助于在测试期间注入不同的实现(即test double)。

例如,调用数据库或Web服务的DAO可以被返回存根数据的实现替换。