我读过各种关于测试中模仿和存根的文章,包括Martin Fowler的《Mocks Aren't Stubs》,但我仍然不理解其中的区别。


当前回答

Stub帮助我们运行测试。怎么做?它给出了有助于运行测试的值。这些值本身不是真实的,我们创建这些值只是为了运行测试。例如,我们创建一个HashMap来提供与数据库表中的值相似的值。因此,我们不直接与数据库交互,而是与Hashmap交互。

Mock是一个运行测试的伪对象。我们在这里输入assert。

其他回答

测试对象根据某些提示(函数调用)或其他刺激来执行动作。下面是测试情况的具体例子。

场景——EMT学生考试

一名学生学习成为一名紧急医疗技术员。如果你对这个测试情况不熟悉,可以去看Ian Gallagher在《无耻之徒》第六季第十集的节目。

为了测试目的,寻找各种疾病的患者太昂贵了。相反,我们使用角色。我们问测试对象(Ian)"当你到达现场发现病人已经不能动弹,失去知觉你首先要做什么?"伊恩回答说:“我检查现场是否安全。”测试指导老师说“现场是安全的”。

教师(和演员)能够向测试对象的问题注入任意答案。

在这里,教练(和演员)是一个模拟。医学培训与计算机科学家一样使用这个术语(例如模拟代码模拟)。

场景——注册一个网站

你正在测试雅虎,一个你听说过的新的电子邮件服务。为了注册,你必须提供你的生日和其他侵入性问题的答案。

该网站要求你年满21岁。输入1970年1月1日。它满足了需求,并且将您从实现记住我的生日并输入它的工作流的费力过程中拯救出来。

这个日期是存根。这个词的用法只适用于计算机科学。

存根用于您在测试中设置的具有预期返回值的方法。 mock用于void方法,这些方法在调用时的Assert中进行验证。

非常清楚和实际:

Stub:实现要伪造的类/对象的方法的类或对象,并且总是返回你想要的东西。

JavaScript示例:

var Stub = {
   method_a: function(param_a, param_b){
      return 'This is an static result';
   }
}

Mock:与存根相同,但是它增加了一些逻辑,当一个方法被调用时“验证”,这样你就可以确定某个实现正在调用该方法。

正如@mLevan所说,假设你正在测试一个用户注册类。在调用Save之后,它应该调用SendConfirmationEmail。

一个非常愚蠢的代码

var Mock = {
   calls: {
      method_a: 0
   }

   method_a: function(param_a, param_b){
     this.method_a++; 
     console.log('Mock.method_a its been called!');
   }
}

我认为他们之间最重要的区别是他们的意图。

让我试着用WHY stub和WHY mock来解释它

假设我正在为我的mac twitter客户端的公共时间轴控制器编写测试代码

下面是测试示例代码

twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline

STUB:到twitter API的网络连接非常慢,这使得我的测试很慢。我知道它将返回时间轴,所以我制作了一个模拟HTTP twitter API的存根,这样我的测试将非常快地运行它,即使我离线也可以运行测试。 MOCK:我还没有写任何我的UI方法,我不确定我需要为我的UI对象写什么方法。我希望通过编写测试代码了解我的控制器如何与我的ui对象协作。

通过编写mock,您可以通过验证期望是否满足来发现对象的协作关系,而stub仅模拟对象的行为。

如果您想了解更多关于模拟的知识,我建议您阅读这篇文章:http://jmock.org/oopsla2004.pdf

存根是为测试目的而构建的伪对象。mock是记录预期调用是否有效发生的存根。