如果我EXPECT_CALL
在同一个对象的同一个模拟对象上调用两次TEST_F
。。。怎么了?
期望值是否附加到了模拟对象上,还是第二次调用消除了第一次调用的效果?
我发现After子句似乎暗示允许对同一模拟+ EXPECT_CALL的多次调用。
是的,您可以EXPECT_CALL
多次调用同一个模拟对象。只要您确保EXPECT_CALL
在实际使用模拟方法之前就调用了所有方法。否则,您的测试将依赖未定义的行为。从ForDummies:
重要说明:gMock要求在调用模拟函数之前设置期望值,否则行为是不确定的。特别是,您不得交错EXPECT_CALL()和对模拟函数的调用。
如何处理多个电话?该文档非常简单。从ForDummies:
默认情况下,当调用模拟方法时,Google Mock将以与定义相反的顺序搜索期望值,并在找到与参数匹配的有效期望值时停止(您可以将其视为“较新的规则会覆盖较旧的规则。 ”)。
让我们通过检查一些示例来考虑这对gMock用户意味着什么。我假设我们有一个带有以下标头的文件:
#include <gmock/gmock.h>
using namespace ::testing;
struct SomeMock
{
MOCK_CONST_METHOD1(foo, void(int));
};
通过EXPECT_CALL
多次调用的最简单的测试示例:
TEST(Examples, DifferentArgumentsGoingToBeOk)
{
SomeMock mock;
EXPECT_CALL(mock, foo(4)).Times(1); // exp#1
EXPECT_CALL(mock, foo(5)).Times(1); // exp#2
mock.foo(4); // call#1
mock.foo(5); // call#2
}
测试直观地进行:
call#1
与不匹配,exp#2
因此exp#1
尝试并匹配。call#2
与匹配exp#2
。两次呼叫恰好匹配一次,因此被认为满足并通过了测试。
当多个EXPECT_CALL
都能匹配呼叫时,棘手的部分开始。让我们考虑以下示例:
TEST(Examples, TheSameArgumentsGoingToFail) // Test fails!
{
SomeMock mock;
EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
EXPECT_CALL(mock, foo(4)).Times(1); //exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
call#1
匹配exp#2
。gMock会以最初匹配的期望值停止,它根本不会检查exp#1
。call#2
匹配exp#2
。再次exp#1
没有机会被匹配。结果,测试失败,因为exp#2
两次匹配而不是一次,并且exp#1
完全不匹配。在测试输出中打印的所有内容:
/tmp/so/main.cpp:26: Failure // exp#2
Mock function called more times than expected - returning directly.
Function call: foo(4)
Expected: to be called once
Actual: called twice - over-saturated and active
/tmp/so/main.cpp:25: Failure // exp#1
Actual function call count doesn't match EXPECT_CALL(mock, foo(4))...
Expected: to be called once
Actual: never called - unsatisfied and active
同样重要的是,增加新的期望值不会禁用或删除旧的期望值。他们仍然能够通过您的测试!
TEST(Examples, NewExpectCallDoesNotEraseThePreviousOne) // Test fails!
{
SomeMock mock;
EXPECT_CALL(mock, foo(4)).Times(1); // exp#1
EXPECT_CALL(mock, foo(4)).Times(2); // exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
无论call#1
和call#2
比赛的exp#2
。结果exp#2
满足了,但是由于exp#1
匹配次数不够,测试将失败。
如果由于某种原因需要编写类似的测试TheSameArgumentsGoingToFail
,则可以使用多种技术来防止exp#2
第二次匹配。请参考文档InSequence的用法,RetiresOnSaturation:
TEST(Examples, InSequenceExample)
{
SomeMock mock;
Sequence seq;
EXPECT_CALL(mock, foo(4)).Times(1).InSequence(seq); //exp#1
EXPECT_CALL(mock, foo(4)).Times(1).InSequence(seq); //exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
TEST(Examples, InSequenceExampleSecondApproach)
{
SomeMock mock;
InSequence seq;
EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
EXPECT_CALL(mock, foo(4)).Times(1); //exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
TEST(Examples, RetiresOnSaturationExample)
{
SomeMock mock;
EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
EXPECT_CALL(mock, foo(4)).Times(1).RetiresOnSaturation(); //exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
TEST(Examples, AfterExample)
{
SomeMock mock;
auto& exp1 = EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
EXPECT_CALL(mock, foo(4)).Times(1).After(exp1); //exp#2
mock.foo(4); // call#1
mock.foo(4); // call#2
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句