返回

解析 Golang 测试(4)- 傻傻分不清的 Mock、Stub、Fake

后端

Mock 与 Stub:虚拟对象的异同

在单元测试中,Mock 和 Stub 都是虚拟对象,用于模拟被测代码依赖的外部组件。然而,它们之间存在着一些关键差异:

  • 创建目的不同: Mock 旨在模拟被测代码与外部组件的交互行为,而 Stub 则专注于模拟外部组件的特定状态或输出。
  • 灵活性不同: Mock 通常允许对行为进行动态配置和验证,而 Stub 通常是预先配置的,其行为不可改变。
  • 应用场景不同: Mock 适用于需要验证被测代码与外部组件交互行为的情况,而 Stub 适用于需要模拟外部组件特定状态或输出的情况。

举个例子,假设我们需要测试一个函数 calculate(), 该函数依赖于一个外部组件 external_component(). 我们可以使用 Mock 来模拟 external_component() 的行为,并验证 calculate() 是否按照预期调用了 external_component()。而如果我们只需要模拟 external_component() 返回一个特定的值,我们可以使用 Stub 来实现。

Fake:伪造对象的本质

Fake 与 Mock 和 Stub 不同,它不是虚拟对象,而是真正存在的对象。Fake 通常用于模拟外部组件,但它不是被测代码的实际依赖项。相反,它是一个伪造的对象,专门用于测试目的。

Fake 通常具有以下特点:

  • 轻量级: Fake 通常比 Mock 和 Stub 更轻量级,因为它不需要像 Mock 和 Stub 那样具有复杂的行为和验证功能。
  • 简单性: Fake 通常更简单,因为它只需要模拟外部组件的必要行为,而不需要模拟所有细节。
  • 适用性: Fake 适用于需要模拟外部组件的特定行为或状态的情况,但不适合需要验证被测代码与外部组件交互行为的情况。

举个例子,假设我们需要测试一个函数 save(),该函数将数据保存到数据库中。我们可以使用 Fake 来模拟数据库,并伪造数据保存操作。这样,我们可以测试 save() 函数是否按照预期将数据保存到数据库中,而无需实际访问数据库。

Dummy:无足轻重的替代者

Dummy 是最简单的替代对象,它通常只是一个空对象,不具有任何行为或状态。Dummy 通常用于占位,以便被测代码能够正常运行。

Dummy 通常具有以下特点:

  • 极简主义: Dummy 是最简单的替代对象,它不具有任何行为或状态。
  • 通用性: Dummy 可以用于任何需要替代对象的地方,因为它没有任何特殊的功能或行为。
  • 适用性: Dummy 适用于需要占位以使被测代码能够正常运行的情况,但不适合需要模拟外部组件行为或状态的情况。

举个例子,假设我们需要测试一个函数 parse(), 该函数将字符串解析为数字。我们可以使用 Dummy 来代替 strconv.ParseInt() 函数,以便 parse() 函数能够正常运行。这样,我们可以测试 parse() 函数是否按照预期将字符串解析为数字,而无需实际调用 strconv.ParseInt() 函数。

Test Double:替代对象的统称

Test Double 是一个统称,用于所有用于替代被测代码依赖项的替代对象。Test Double 包括 Mock、Stub、Fake 和 Dummy。

选择合适的 Test Double 取决于测试的具体需求。在某些情况下,Mock 是最好的选择,而在另一些情况下,Stub、Fake 或 Dummy 更合适。

结论

本文介绍了 Mock、Stub、Fake、Dummy 和 Test Double 等替代对象的概念,以及它们之间的区别。通过理解这些概念,我们可以更好地选择合适的替代对象来进行单元测试,从而提高测试的质量和效率。