Google模拟-我可以在同一个模拟对象上多次调用EXPECT_CALL吗?
如果我在同一 TEST_F
中的同一模拟对象上两次调用 EXPECT_CALL
。 。 。会发生什么事情?
If I call EXPECT_CALL
twice on the same mock object in the same TEST_F
. . . what happens?
期望值是否附加到模拟对象上,还是第二次调用会抹去第一次调用的效果?
Are the expectations appended to the mock object or does the second call erase the effects of the first call?
我发现 After子句似乎暗示允许对同一模拟+ EXPECT_CALL进行多次调用。
I found The After Clause which appears to imply that multiple calls to same mock + EXPECT_CALL are allowed.
是的,您可以在同一个模拟对象上多次调用 EXPECT_CALL
。只要您确保在实际使用模拟方法之前就调用了所有 EXPECT_CALL
。否则,您的测试将依赖未定义的行为。来自 ForDummies :
Yes, you can call EXPECT_CALL
on the same mock object multiple times. As long as you assure that all EXPECT_CALL
were called before the mocked methods were actually used. Otherwise your test will rely on undefined behavior. From ForDummies:
重要说明:gMock要求在调用模拟函数之前设置期望值,否则行为未定义。特别是,您不得交错EXPECT_CALL()和对模拟函数的调用。
Important note: gMock requires expectations to be set before the mock functions are called, otherwise the behavior is undefined. In particular, you mustn't interleave EXPECT_CALL()s and calls to the mock functions.
如何处理多个调用?该文档非常简单。来自 ForDummies :
How multiple calls will be handled? The documentation is really straightforward. From ForDummies:
默认情况下,调用模拟方法时,Google Mock将按照定义的相反顺序搜索
期望值,并在找到与参数匹配的
有效期望时停止(您可以认为其中的
是新规则优先于旧规则。)。
By default, when a mock method is invoked, Google Mock will search the expectations in the reverse order they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones.").
让我们通过检查一些示例来考虑这对gMock用户意味着什么。我假设我们有一个带有以下标头的文件:
Let's consider what this means for the gMock user, by checking some examples. I assume that we have a file with following header:
#include <gmock/gmock.h>
using namespace ::testing;
struct SomeMock
{
MOCK_CONST_METHOD1(foo, void(int));
};
通过测试的最简单示例是调用 EXPECT_CALL
多次:
The simplest example of passing test that calls EXPECT_CALL
multiple times:
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
}
测试直观地进行:
-
呼叫#1
与exp#2 $ c $不匹配c>,因此尝试并匹配了
exp#1
。 -
call#2
与exp#2
匹配。
-
call#1
does not match withexp#2
soexp#1
is tried and matches. -
call#2
matches withexp#2
.
两个调用完全匹配一次,因此
Both calls matched exactly once, thus they are considered satisfied and the test passes.
当多个 EXPECT_CALL
能够匹配通话时,棘手的部分开始。让我们考虑以下示例:
The tricky part starts when multiple EXPECT_CALL
are able to match the call. Let's consider the following example:
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
没有机会被匹配。 - The
call#1
matches theexp#2
. gMock stops at first matched expectation, it won't check theexp#1
at all. - The
call#2
matches theexp#2
. Again theexp#1
does not have chance to be matched.
结果测试失败,因为 exp#2
被匹配两次而不是一次,并且 exp#1
在所有。在测试输出中打印的所有内容:
As a result the test fails as the exp#2
gets matched twice instead of once and exp#1
is not matched at all. All that is printed in the test output:
/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
此外,重要的是,增加新的期望值不会禁用或删除旧的期望值。他们仍然能够通过您的测试!
Also, it is important, that adding new expectancy won't disable or remove old ones. They are still able to fail your test!
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
的匹配时间不够,测试将失败
Both call#1
and call#2
matches the exp#2
. As a result the exp#2
is satisfied, but the test will fail as exp#1
was not matched enough times.
如果出于某种原因,您需要编写 TheSameArgumentsGoingToFail
之类的测试,则可以使用多种方法防止 exp#2
第二次匹配。请参阅文档 InSequence使用情况, RetiresOnSaturation :
If for some reason, you need to write a test like TheSameArgumentsGoingToFail
, you can use a number of techniques to prevent exp#2
from matching second time. Please refer to the documentation InSequence usage, 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
}