什么是模拟,什么时候应该使用它?
我刚刚阅读了关于mock objects的维基百科文章,但我仍然不完全清楚其目的。看起来它们是由测试框架创建的对象,当实际对象太复杂或不可预知时(您完全知道模拟对象的值是因为完全控制了它们而确定的)。什么是模拟,什么时候应该使用它?
但是,我的印象是,所有的测试都是用已知值的对象完成的,所以我必须错过一些东西。例如,在课程项目中,我们的任务是使用日历应用程序。我们的测试套件由事件对象组成,我们知道它们是什么,所以我们可以测试多个事件对象,各种子系统和用户界面之间的交互。我猜这些是模拟对象,但我不知道为什么你不这样做,因为没有已知值的对象,你不能测试一个系统。
模拟对象不仅仅是一个已知值的对象。它是一个与复杂对象具有相同接口的对象,不能在测试中使用(如数据库连接和结果集),但是可以在测试中控制实现。
有一些模拟框架允许您即时创建这些对象,本质上允许您说出如下内容:使用foo方法将对象设为int并返回一个bool。当我传递0时,它应该返回true。然后你可以测试使用foo()的代码,以确保它适当地反应。
Martin Fowler的对嘲讽一个伟大的文章:
想想客户端和服务器软件的经典案例。要测试客户端,您需要服务器;要测试服务器,你需要客户端。这使得单元测试几乎不可能 - 不使用模拟。如果你嘲笑服务器,你可以单独测试客户端,反之亦然。
模拟的重点不在于重复其嘲讽事物的行为。它更像是一个简单的状态机,它的状态变化可以通过测试框架来分析。因此,客户端模拟可能会生成测试数据,将其发送到服务器,然后分析响应。您期望对特定请求有特定响应,因此您可以测试是否获得该请求。
我的一切@Lou Franco说,你一定要阅读测试的优秀Martin Fowler的文章同意成倍于@Lou佛朗哥点你去。
任何测试双(伪造,存根或模拟)的主要目的是隔离测试中的对象,以便您的单元测试仅测试该对象(而不是它的依赖关系以及与之协作或交互的其他类型)。
提供您的对象所依赖的接口的对象可以用来代替实际的依赖关系,因此可以期望发生某些交互。这可能很有用,但在基于状态和基于交互的测试方面存在一些争议。过度使用模拟期望会导致脆弱的测试。
测试双打的另一个原因是删除数据库或文件系统或其他昂贵的设置或执行耗时操作的类型的依赖关系。这意味着您可以将所需的对象单元测试所需的时间降到最低。
下面是一个示例:如果您正在编写填充数据库的代码,则可能需要检查特定的方法是否已将数据添加到数据库。
设置用于测试的数据库副本有一个问题,即如果您假设在调用测试方法之前没有记录,之后有一条记录,则需要将数据库回滚到以前的状态,因此增加了运行测试的开销。
如果您认为只有一条记录比以前多了,它可能会与连接到同一数据库的第二个测试者(甚至是第二个测试在同一代码中)发生冲突,从而导致依赖性并使测试变得脆弱。
该模拟允许您保持测试彼此独立并且易于设置。
这只是一个例子 - 我确信其他人可以提供更多。
我同意关于此主题的其他贡献者100%,尤其是与Martin Fowler文章的建议。
您可能对我们的书感兴趣,请参阅http://www.growing-object-oriented-software.com/。它在Java中,但这些想法仍然适用。
这是一个断开的链接。 – 2010-03-14 19:06:52
真棒文章链接。谢谢 – 2008-11-13 20:30:28