【问题标题】:Googlemock Pause ExpectationsGooglemock 暂停预期
【发布时间】:2021-05-12 07:24:11
【问题描述】:

我有一个场景,我希望对模拟对象上的函数进行一些调用,然后对于某些代码路径,我需要确保不调用该函数,然后再调用它。有没有办法做到这一点?

EXPECT_CALL(mockObj, 1); 
foo(1);

// Expect this call at the first invocation of foo(2)
EXPECT_CALL(mockObj, 2); 
foo(2);

// These calls should not call my mockObj again, the above expectation is 
// intended for the first invocation of foo(2)
foo(2);
foo(2);

// And now, i expect it to be called
EXPECT_CALL(mockObj, 3); 
foo(3);

我可能会检查 EXPECT_CALL(mockObj, 2);只调用了预期的次数,但我还想确认它仅在第一次调用 foo(2) 时调用,而不是在随后调用 foo(2) 时调用。 你能告诉我在 gmock 中实现这一点的任何方法吗?

【问题讨论】:

标签: c++ googletest googlemock


【解决方案1】:

Gmock cookbook 建议使用虚拟检查点模拟函数

using ::testing::MockFunction;

TEST(FooTest, InvokesMyMockCorrectly) {
  MyMock mockObj;
  // Class MockFunction<F> has exactly one mock method.  It is named
  // Call() and has type F.
  MockFunction<void(string check_point_name)> check;
  {
    InSequence s;

    EXPECT_CALL(mockObj, 1);
    EXPECT_CALL(check, "1");
    EXPECT_CALL(mockObj, 2);
    EXPECT_CALL(check, "2");
    EXPECT_CALL(check, "3");
    EXPECT_CALL(mockObj, 3);
  }
  
  foo(1);
  check.Call("1");

  foo(2);
  check.Call("2");

  foo(2);
  foo(2);

  check.Call("3");
  foo(3);
}

或使用 Mock::VerifyAndClearExpectations() 重置模拟,然后设置新的期望。

否则,某些答案中建议的对模拟和 EXPECT_CALL 的交错调用是未定义的行为:

重要提示:gMock 要求在调用模拟函数之前设置期望值,否则行为未定义。特别是,您不能将 EXPECT_CALL() 和对模拟函数的调用交错。

来自gmock for dummies,另见Interleaving EXPECT_CALL()s and calls to the mock functions

【讨论】:

    【解决方案2】:

    我会把它分成几个测试用例:

    TEST(Foo, CalledOnFirstInvoation) {
      EXPECT_CALL(mockObj, 1); 
      foo(1);
    }
    
    TEST(Foo, CalledAgainWhenUsingDifferenArgument) {
      EXPECT_CALL(mockObj, 2); 
      foo(1);
      foo(2);
    }
    
    TEST(Foo, NotCalledWhenUsingSameArgument) {
      EXPECT_CALL(mockObj, 2); 
      foo(1);
      foo(2);
      foo(2);
      foo(2);
    }
    
    TEST(Foo, CalledAgainWhenUsingYetAnotherArgument) {
      EXPECT_CALL(mockObj, 3); 
      foo(1);
      foo(2);
      foo(2);
      foo(3);
    }
    

    【讨论】:

      【解决方案3】:

      你想要这样的东西吗?

      EXPECT_CALL(mockObj, 1).Times(0);
      EXPECT_CALL(mockObj, 2).Times(0); // #2
      EXPECT_CALL(mockObj, 3); // #3
      
      {
        EXPECT_CALL(mockObj, 1); // #1
        foo(1); // Matches #1
      }
      
      {
        EXPECT_CALL(mockObj, 2); // #4
        // Expect this call at the first invocation of foo(2)
        foo(2); // Matches #4
      }
      
      // These calls should not call my mockObj again, the above expectation is 
      // intended for the first invocation of foo(2)
      foo(2); // Matches #2
      foo(2); // Matches #2
      
      // And now, i expect it to be called
      foo(3); // Matches #3
      

      【讨论】:

      • 谢谢!在自己的范围内拥有期望,就像一种魅力。
      • 请检查@IanMartin 的答案。交错 EXPECT_CALL() 和调用模拟函数是未定义的行为。
      猜你喜欢
      • 1970-01-01
      • 2021-12-21
      • 2018-06-16
      • 2013-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-05
      • 2022-12-16
      相关资源
      最近更新 更多