是的,您可以致电EXPECT_CALL
多次在同一个模拟对象上。只要你保证一切EXPECT_CALL
在实际使用模拟方法之前调用。否则你的测试将依赖于未定义的行为。从对于傻瓜来说 https://github.com/google/googletest/blob/main/docs/gmock_for_dummies.md#using-mocks-in-tests:
重要提示:gMock 要求在调用模拟函数之前设置期望,否则行为是未定义的。特别是,您不能交错 EXPECT_CALL() 和对模拟函数的调用。
如何处理多个呼叫?该文档非常简单。从对于傻瓜来说 https://github.com/google/googletest/blob/main/docs/gmock_for_dummies.md#using-multiple-expectations-multiexpectations:
默认情况下,当调用模拟方法时,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
so 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
}
- The
call#1
匹配exp#2
。 gMock 在第一个匹配的期望处停止,它不会检查exp#1
at all.
- The
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
}
Both call#1
and call#2
匹配exp#2
。结果是exp#2
满意,但测试将失败,因为exp#1
匹配次数不够。
如果由于某种原因,您需要编写类似的测试TheSameArgumentsGoingToFail
,您可以使用多种技术来防止exp#2
从第二次匹配开始。请参考文档顺序使用 https://github.com/google/googletest/blob/main/docs/gmock_for_dummies.md#ordered-vs-unordered-calls-orderedcalls, 饱和退休 https://github.com/google/googletest/blob/main/docs/gmock_for_dummies.md#all-expectations-are-sticky-unless-said-otherwise-stickyexpectations:
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
}