繁体   English   中英

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

[英]How do interfaces make unit testing and mocking easier?

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

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

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

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

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

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

如果您的对象模型过于复杂和混乱 (例如,您的接口严重依赖于其他类型/接口), 接口将无济于事 ; 然后实施/嘲笑这一切都是一种痛苦

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM