在使用ON_CALL和EXPECT_CALL指定默认操作时,我不理解两者之间的区别。
到目前为止,我注意到/了解到有两种方法可以调整模拟的默认操作:
ON_CALL(mock, methodX(_)).WillByDefault(Return(0x01));
或
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(Return(0x01));
谁能跟我解释一下:
发布于 2012-12-19 17:40:35
这两种说法之间有细微但显著的差别。EXPECT_CALL
在模拟调用上设置期望。写作
EXPECT_CALL(mock, methodX(_)).WillRepeatedly(do_action);
告诉gMock,methodX
可以在mock
上被多次调用,并带有任何参数,如果是的话,mock
将执行do_action
。另一方面,
ON_CALL(mock, methodX(_)).WillByDefault(do_action);
告诉gMock,每当methodX
在mock
上被调用时,它都应该执行do_action
。在这样一个场景中,这个特性很有帮助,在这个场景中,您必须在模拟上写很多期望,而且大多数/所有这些都必须指定相同的操作--特别是当它很复杂的时候。您可以在ON_CALL
中指定该操作,然后在不显式指定操作的情况下编写EXPECT_CALL
。例如,
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
指定行为:
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
,如果您编写
ON_CALL(mock, Sign(Gt(0), _)).WillByDefault(Return(1));
EXPECT_CALL(mock, Sign(10, _));
调用mock.Sign(10)
将返回1,因为ON_CALL
为EXPECT_CALL
指定的调用提供默认行为。但如果你写
EXPECT_CALL(mock, Sign(Gt(0), _).WillRepeatedly(Return(1));
EXPECT_CALL(mock, Sign(10, _));
对mock.Sign(10, p)
的调用将返回0。它将与第二个预期相匹配。该期望没有指定任何显式操作,gMock将为其生成一个默认操作。该默认操作是返回返回类型的默认值,对于int
是0。在这种情况下,第一个期望将被完全忽略。
发布于 2012-12-18 13:23:04
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():
ON_CALL(mock_object, method(matchers))
.With(multi_argument_matcher) ?
.WillByDefault(action);
发布于 2021-08-25 13:36:46
这是关于ON_CALL
和EXPECT_CALL
之间最重要的区别的“官方”解释,如gMock食谱中所解释的。
基本上有两个构造来定义模拟对象的行为:ON_CALL
和EXPECT_CALL
。
区别是什么?
ON_CALL
定义了在调用模拟方法时会发生什么,但并不意味着对调用的方法有任何期望。
EXPECT_CALL
不仅定义了行为,而且还为给定的次数(以及指定顺序时的给定顺序)设置了方法必须用给定参数调用的期望()。
既然EXPECT_CALL
做得更多,难道不是比ON_CALL
更好吗?
不怎么有意思。每个EXPECT_CALL
都会对被测试代码的行为添加一个约束。有比必要的更多的约束是不好的,甚至比没有足够的约束更糟糕。
这可能有违直觉。验证越多的测试怎么会比验证越少的测试更糟糕?验证不就是整个测试的重点吗?
答案在于测试应该验证什么。一个很好的测试验证了代码的契约。如果测试过度指定,那么它就没有给实现留下足够的自由。因此,在不违反约定的情况下更改实现(例如重构和优化)(应该是非常好的)可以破坏这样的测试。然后,您必须花时间修复它们,但在下次更改实现时,只会再次看到它们被破坏。
请记住,在一个测试中不需要验证多个属性。事实上,在一次测试中只验证一件事情是一种很好的方式。如果您这样做,一个bug可能只会中断一个或两个测试,而不是几十个测试(您更愿意调试哪种情况?)如果您也习惯于给出测试描述性名称,告诉它们验证了什么,那么您通常可以很容易地从测试日志本身猜出问题所在。
因此,默认情况下使用ON_CALL
EXPECT_CALL
,并且只有在实际要验证调用是否已发出时才使用。
https://stackoverflow.com/questions/13933475
复制相似问题