我一直在阅读Mocks and Stubs,他们的差异和用途。我仍然有点困惑,但我想我已经得到了它的主旨。
现在我对应用程序感到疑惑。我可以看到创建"假"在测试场景中的对象,其中实际对象太复杂而无法测试一个方面。
但是让我们考虑一下我的应用:我正在研究计算几何库。我们的库定义了点,线,linesegments,向量,多边形和多面体,以及一堆其他对象和所有常见的几何操作。任何给定对象都存储为点或方向列表或较低级别对象。但是这些对象都不会花费超过几毫秒的时间来生成。
当我测试这个库时,在任何地方使用Mocks / Stubs是否有意义?
现在我们只使用特定的测试用例。我们称它们为存根,但我认为它们不符合存根的技术定义。你觉得那个更好的词汇是什么? "的TestCases&#34 ;? "实施例"
SourceCode:https://bitbucket.org/Clearspan/geometry-class-library/src
编辑:请注意,我们正在努力争取所有几何对象的不变性,因此只测试操作结果,而不是对初始对象进行状态更改。
答案 0 :(得分:3)
根据经验,当你需要模拟行为时使用Mocks,当测试中唯一重要的事情是你正在与之通信的对象的状态时使用存根。
考虑到你对帖子所做的编辑,当你需要接收一个不可变对象时使用一个存根,但是当你需要调用对象公开的操作然后去模拟时,这样你就不会失败了由于另一个类实现中的错误而进行的测试。
答案 1 :(得分:3)
mock和stub之间的根本区别在于mock可以使你的测试失败。存根不能。存根用于保证正确的程序流程。它绝不是断言的一部分。
请注意,mock也可用于保证流量。换句话说,每个模拟也是一个存根,存根永远不是模拟。由于现在这种重叠的职责你没有看到模拟和存根之间的区别,框架设计师会寻求更一般的术语(如fake,substitute或catch-all mock)。
这种实现(mock - assert,stub - flow)帮助我们缩小了一些使用场景。从更容易的开始......
正如我所提到的,在断言中使用了模拟。当您的组件的预期行为是时,它应与该其他组件对话 - 请使用mock。所有那些
emailSender.SendEmail(email);
endOfDayRunner.Run();
jobScheduler.ScheduleJob(jobDetails);
只能通过询问“是否用这样的参数调用ScheduleJob
来测试?”这是你去模拟的地方。通常这将是模拟的唯一使用场景。
有了存根,它有点不同。是否使用存根是设计问题。一旦你遵循常规的松散耦合,基于依赖注入的设计,最终你会得到很多接口。
现在,在测试时,如何从界面返回值?您要么存根,要么使用真正的实现。每种方法都有其优点和缺点:
Angle
类更改CoordinateSystem
可能会失败...这样的行为是否可取? 我们到达了最后和问题的实际部分。您的单元测试的范围是什么?什么是 单元 ?可以CoordinateSystem
与其内部工作方式和依赖关系(Angle
,Point
,Line
分离,并且它们可以被删除吗?或者更重要的是,它们应该是吗?
您始终需要确定您的单位。是CoordinateSystem
单独使用还是Angle
,Line
和Point
是否可以发挥重要作用?在许多情况下,该单元将由方法及其周围生态系统形成,包括域对象,辅助类,扩展,有时甚至是其他方法和其他类。
当然,你可以将它们分开并一直存在但是......它真的是你的单位吗?