我刚刚看了这个关于单元测试的有趣的 YouTube 视频(它是带有假字幕的希特勒,因为他的团队没有做好单元测试而大骂他的团队——如果你有幽默感,请跳过它),其中存根受到严厉批评。但我不明白存根有什么问题。
我还没有开始使用模拟框架,也没有开始感受到不使用模拟框架的痛苦。
选择手写存根和赝品而不是模拟(如 Rhinomock 等),我是否会在某个时候受到伤害?(使用福勒分类法)
在模拟存根和手写存根之间进行选择有哪些注意事项?
我刚刚看了这个关于单元测试的有趣的 YouTube 视频(它是带有假字幕的希特勒,因为他的团队没有做好单元测试而大骂他的团队——如果你有幽默感,请跳过它),其中存根受到严厉批评。但我不明白存根有什么问题。
我还没有开始使用模拟框架,也没有开始感受到不使用模拟框架的痛苦。
选择手写存根和赝品而不是模拟(如 Rhinomock 等),我是否会在某个时候受到伤害?(使用福勒分类法)
在模拟存根和手写存根之间进行选择有哪些注意事项?
存根没有任何问题,存根、模拟......和间谍都有空间。都是“测试替身”,但目的不同,如Mocks and Stubs are not Spies 中所述:
[...] 在继续之前,我想澄清和定义一些在这里使用的术语,我最初在 Gerard Meszaros 的xUnit Patterns book中发现了这些术语。
- 虚拟对象是传递给被测系统但从未使用过的占位符对象。
- 测试存根为被测系统提供间接输入
- 测试间谍提供了一种方法来验证被测系统是否执行了正确的间接输出
- 模拟对象为被测系统提供间接输入和验证间接输出的方法
[...] 您可以让这张方便的图表指导您的决定:
PS:Mockito - Block 上的新 Mock 框架也值得一读。
我使用以下术语(由单元测试艺术的作者 Roy Osherove 介绍):
如果您告诉它伪造某些东西,以防使用这样或这样的参数调用方法,则假被称为存根。但是,如果您还验证了这样的调用确实发生了或恰好发生了 N 次,那么这种假称为mock。简而言之。假货是存根,除非您在其上调用验证()然后它是模拟的。
显然,在某些情况下您需要使用存根,而在其他情况下需要使用模拟。因此,全面批评存根可能是错误的,而专门使用存根也可能是错误的。
如果您还没有开始使用模拟框架(替代术语:隔离框架),您应该密切关注它们并经常重新评估您的选择。我很快就从手动模拟到 NMock2 再到 Moq。这是一个有趣的程序员调查,显示他们使用什么。手动模拟/存根是少数,但并不少见。
Mocks 更容易投入使用。它们是您的类的真实实例,预先存根,能够以最少的样板覆盖任何方法的操作。
有很多小考虑,例如:如果您不想处理任何方法,您可以让它充当无操作或测试失败 - 您的选择 - 但无论哪种方式几乎都没有代码.
当你结束一个类时,你会得到多少样板文件?如果您的课程是最终课程,您将如何处理?你是先把存根放在类路径上,还是使用不同的源?
我建议从 mocks 开始——它更容易。
使用存根代替模拟没有任何问题。
如果您想获得技术知识,模拟是具有可以验证的期望的“智能”对象。存根是返回预设值的虚拟对象。请参阅模拟不是存根。
但是很多人(包括我自己)更喜欢使用 stub 进行状态测试,而不是使用 mock 进行行为测试。您将一个存根注入到被测类中,调用一个方法,然后检查被测类的状态。与断言类的内部调用带有参数 Y 的模拟对象的方法 X 相比,它倾向于进行不那么脆弱的测试。
我不认为你是在一个受伤的世界。如果您还没有开始感到痛苦,那么您可能还不需要隔离/模拟框架。如果你这样做了,有手写的存根/假货不会伤害任何东西。
如果您有很多接口,或者您的接口有很多方法,那么隔离/模拟框架可以比手动编码存根节省大量时间。
我非常喜欢起订量;我发现它比 Rhino Mocks 更容易用于创建存根。
模拟和存根用于实现真正的单元测试。您只需模拟所有依赖项,并单独对您的类进行单元测试。
我目前正在使用MOQ进行模拟和存根。