模拟不是拐杖,模拟是规范

在许多绕轨道运行的伪距TDD中,有一些无视双精度测试,尤其是与它们的可笑名称有关。

他们会以某种方式自豪地称呼他们,否则会产生莫名其妙,存根,假冒的感觉-如果不使用它,我们实际上并不会损失任何东西。 (与“集成测试”和“实际依赖项”相反)。

但是,您可以更改观点。 最后,模拟不仅并没有太多地支持依赖项组件,而是指定了依赖项的行为。 “真正的”实现是我们引以为傲的想法的某种当前的,可能是错误的体现。

从这个意义上讲,每次我们写

when(mockDependency.method(inputValue)).thenReturn(returnValue)

我们记录了一些组件行为。

因此,有几个后果。

模拟对象在词汇和含义上都与实际测试规范紧密相关。 两者都使我们着重于需求和场景,而不是当前实现的功能。

在使用Mockito之类的框架时,关于要润湿的组件的声明对我们来说有点分散注意力的事实分散在客户端类之间,并且很难跟踪它们。 从这种意义上讲,具有预定义行为的显式后代类比Mockito之类的模拟类更可取,因为它们使您可以封装脚本并一目了然地查看它们。

因此,可以将脚本类ValidOrderProviderStub,ExpiredOrderProviderStub,InvalidOrderIdException_OrderProviderStub,OnlyOnceOrderProvider等放在同一程序包中,并且一次可用于所有测试,并将它们添加到每个OrderProvider类。

这包括易于实现的Spy类。

另外,这种方法执行起来更快,并且无需使用反射即可工作。

因此,在阅读代码时,我们可以约定:mok的存在确认了脚本的可能性,而mok的存在则阻止了这种脚本的存在。 如果我们禁止客户端类编写期望的模拟,那么在搜索NullOrderProvider时会发现没有合适的模拟,因为null永远不会返回,因此对这种情况进行测试是没有意义的。

如果mok是规范,则mok反映了我们的组件计划,可以而且应该在实现之前编写它们。

如果mok是规范,则它是分层的,并根据某些条件反映组件的行为。

因此,我们的moki可能乘以太多:无条件的moki总是返回相同的值,以及具有内部条件的moki,例如forIdOne_returningOne_forIdTwo_ReturningTwo_OrderProvider。 最后一个枚举,您只需要创建一个具有适当行为的FakeOrderProvider,该行为应与实际实现同步。

因此,如果mok是某种行为的规范,那么组件的实现只不过是将组件的行为与其mok进行同步。

也许这是反对小怪的主要论点-需要将它们的行为与当前的实际实现同步,我们下一次将分别讨论。

Source: https://habr.com/ru/post/zh-CN474484/


All Articles