最近看到一篇关于mock的文章,觉得挺有道理的,,简单总结分享一下,原文在这里:https://levelup.gitconnected.com/why-mocks-are-considered-harmful-b4e8fe60478d。 文章的观点很简单,就是mock其实是弊大于利的。

自动化测试涉及到很多技术,其中mock技术我们应该尽量避免使用。mock用的好其实也只是锦上添花,用的不好的话则会给你带来一些过度的自信。

首先看下什么是mock。mock其实就是模拟代码中的一些外部访问行为,比如访问第三方的付款api或者是对数据库进行访问,这会给单元测试带来一些好处

  • 运行加速,因为你不需要访问额外的服务;
  • 提升稳定性,第三方服务提供商的一些不稳定因素被规避掉了

不过mock是为一些具有副作用的代码服务的,也就是说这些代码其实是依赖于外部服务,并不是依赖于各种参数的输入。我们可以把函数分成两类

  • 纯粹的函数:没有外部依赖的函数
  • 不纯粹的函数:有外部依赖的函数

mock带来的问题

mock不等同于其替换掉的服务。

比如你把代码中数据库访问的部分给mock掉了,这意味着你的代码可能会在有mock的时候工作良好,然而你还是需要进行集成测试以确保在没有mock的时候也可以正常工作。

不可能进行特性平替

如果你使用的是简单的mock方式,那么mock可能不会返回一些有用的数据,你花在mock上的时间越多,mock返回的data可能会约实用。然而mock不能平替被mock系统的方方面面。

开发了mock但不使用其实就是浪费时间

如果你开发了数据库的mock但从不使用的话,这就是浪费时间了。在现实世界中这是很有可能发生的,因为代码可能需要获取一些真实配置去做初始化,而mock的时候却很难满足这一条件。

如何去找到mock的替代方案

很简单,就是重构代码,把代码重构成纯粹的函数和不纯粹的函数两种,纯粹的函数是不需要mock就可以测试的,,不纯粹的函数则可以通过集成测试来进行验证。

举个例子

def logic():
    x = addition(1, 3)
    y = multiplication(2, 4)
		z = x + y
		database_write(z)
    return 

上面的函数就是不纯粹的函数,因为其访问了db,然而我们还是可以把这个函数重构成1个纯粹函数和另一个不纯粹的函数

def calc(a, b, c, d):
		x = addition(a,b)
		y = multiplication(c,d)
		return x + y

def logic():
		z = calc(1, 5, 2, 4)
		database_write(z)
		return 

这样calc函数可以用单元测试覆盖了,而logic则留给集成测试去考虑吧。

最后尽可能的优化你的自动测试方案,让更多的代码都通过自动化进行覆盖。

总结

mock短期来看可能是一种解决问题的方式,然而长期看来确是一个麻烦的问题。如果你想快速交付软件产品的话,那么你应该少花时间在mock上,多花点时间在重构和自动化测试上面。