Google模拟-我可以在同一个模拟对象上多次调用EXPECT_CALL吗? [英] google mock - can I call EXPECT_CALL multiple times on same mock object?

查看:537
本文介绍了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 ,因此尝试并匹配了 exp#1

  • call#2 exp#2 匹配。

  • call#1 does not match with exp#2 so exp#1 is tried and matches.
  • call#2 matches with exp#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 the exp#2. gMock stops at first matched expectation, it won't check the exp#1 at all.
    • The call#2 matches the exp#2. Again the exp#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
      }
      

      这篇关于Google模拟-我可以在同一个模拟对象上多次调用EXPECT_CALL吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆