首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >设置默认操作/ ON_CALL与EXPECT_CALL

设置默认操作/ ON_CALL与EXPECT_CALL
EN

Stack Overflow用户
提问于 2012-12-18 12:52:41
回答 5查看 119.8K关注 0票数 71

在使用ON_CALL和EXPECT_CALL指定默认操作时,我不理解两者之间的区别。

到目前为止,我注意到/了解到有两种方法可以调整模拟的默认操作:

代码语言:javascript
运行
复制
ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));

代码语言:javascript
运行
复制
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));

谁能跟我解释一下:

  • 两种方法的区别
  • 每一个人的起起落落
  • 什么时候使用它们合适(什么样的设置.)
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-19 17:40:35

这两种说法之间有细微但显著的差别。EXPECT_CALL在模拟调用上设置期望。写作

代码语言:javascript
运行
复制
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(do_action);

告诉gMock,methodX可以在mock上被多次调用,并带有任何参数,如果是的话,mock将执行do_action。另一方面,

代码语言:javascript
运行
复制
ON_CALL(mock, methodX(_)).WillByDefault(do_action);

告诉gMock,每当methodXmock上被调用时,它都应该执行do_action。在这样一个场景中,这个特性很有帮助,在这个场景中,您必须在模拟上写很多期望,而且大多数/所有这些都必须指定相同的操作--特别是当它很复杂的时候。您可以在ON_CALL中指定该操作,然后在不显式指定操作的情况下编写EXPECT_CALL。例如,

代码语言:javascript
运行
复制
ON_CALL(mock, Sign(Eq(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is zero"), Return(0)));
ON_CALL(mock, Sign(Gt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is positive"), Return(1)));
ON_CALL(mock, Sign(Lt(0), _))
  .WillByDefault(DoAll(SetArgPointee<1>("argument is negative"), Return(-1)));

现在,如果您必须编写大量的EXPECT_CALL,则不必每次都要mock指定行为:

代码语言:javascript
运行
复制
EXPECT_CALL(mock, Sign(-4, _));
EXPECT_CALL(mock, Sign(0, _));
EXPECT_CALL(mock, Sign(1, _)).Times(2);
EXPECT_CALL(mock, Sign(2, _));
EXPECT_CALL(mock, Sign(3, _));
EXPECT_CALL(mock, Sign(5, _));

在另一个示例中,假设符号返回int,如果您编写

代码语言:javascript
运行
复制
ON_CALL(mock, Sign(Gt(0), _)).WillByDefault(Return(1));
EXPECT_CALL(mock, Sign(10, _));

调用mock.Sign(10)将返回1,因为ON_CALLEXPECT_CALL指定的调用提供默认行为。但如果你写

代码语言:javascript
运行
复制
EXPECT_CALL(mock, Sign(Gt(0), _).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Sign(10, _));

mock.Sign(10, p)的调用将返回0。它将与第二个预期相匹配。该期望没有指定任何显式操作,gMock将为其生成一个默认操作。该默认操作是返回返回类型的默认值,对于int是0。在这种情况下,第一个期望将被完全忽略。

票数 73
EN

Stack Overflow用户

发布于 2012-12-18 13:23:04

代码语言:javascript
运行
复制
ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));

就像你说的,这两行做的是完全一样的事情,所以根本没有区别。请任意使用任何一种方法来设置默认操作。

然而,有一个逻辑上的区别:

  • ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));意味着方法可能被调用,如果发生这种情况,每个调用都将返回0x01。
  • EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));意味着将调用该方法,并且每个调用都将返回0x01。

顺便说一句,他们的备忘单上有一个设置默认操作,上面写着:

若要自定义特定方法的默认操作,请使用ON_CALL():

代码语言:javascript
运行
复制
ON_CALL(mock_object, method(matchers))
    .With(multi_argument_matcher)  ?
    .WillByDefault(action);
票数 15
EN

Stack Overflow用户

发布于 2021-08-25 13:36:46

这是关于ON_CALLEXPECT_CALL之间最重要的区别的“官方”解释,如gMock食谱中所解释的。

基本上有两个构造来定义模拟对象的行为:ON_CALLEXPECT_CALL

区别是什么?

ON_CALL 定义了在调用模拟方法时会发生什么,但并不意味着对调用的方法有任何期望。

EXPECT_CALL 不仅定义了行为,而且还为给定的次数(以及指定顺序时的给定顺序)设置了方法必须用给定参数调用的期望()。

既然EXPECT_CALL做得更多,难道不是比ON_CALL更好吗?

不怎么有意思。每个EXPECT_CALL都会对被测试代码的行为添加一个约束。有比必要的更多的约束是不好的,甚至比没有足够的约束更糟糕。

这可能有违直觉。验证越多的测试怎么会比验证越少的测试更糟糕?验证不就是整个测试的重点吗?

答案在于测试应该验证什么。一个很好的测试验证了代码的契约。如果测试过度指定,那么它就没有给实现留下足够的自由。因此,在不违反约定的情况下更改实现(例如重构和优化)(应该是非常好的)可以破坏这样的测试。然后,您必须花时间修复它们,但在下次更改实现时,只会再次看到它们被破坏。

请记住,在一个测试中不需要验证多个属性。事实上,在一次测试中只验证一件事情是一种很好的方式。如果您这样做,一个bug可能只会中断一个或两个测试,而不是几十个测试(您更愿意调试哪种情况?)如果您也习惯于给出测试描述性名称,告诉它们验证了什么,那么您通常可以很容易地从测试日志本身猜出问题所在。

因此,默认情况下使用ON_CALL EXPECT_CALL ,并且只有在实际要验证调用是否已发出时才使用。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13933475

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档