gMock 速查表

定义模拟类

模拟普通类

给定

class Foo {
 public:
  virtual ~Foo();
  virtual int GetSize() const = 0;
  virtual string Describe(const char* name) = 0;
  virtual string Describe(int type) = 0;
  virtual bool Process(Bar elem, int count) = 0;
};

(注意 ~Foo() 必须是虚函数),我们可以将其模拟定义为

#include <gmock/gmock.h>

class MockFoo : public Foo {
 public:
  MOCK_METHOD(int, GetSize, (), (const, override));
  MOCK_METHOD(string, Describe, (const char* name), (override));
  MOCK_METHOD(string, Describe, (int type), (override));
  MOCK_METHOD(bool, Process, (Bar elem, int count), (override));
};

要创建一个“友好”的模拟,它会忽略所有不感兴趣的调用;一个“烦人”的模拟,它会警告所有不感兴趣的调用;或一个“严格”的模拟,它会将它们视为失败

using ::testing::NiceMock;
using ::testing::NaggyMock;
using ::testing::StrictMock;

NiceMock<MockFoo> nice_foo;      // The type is a subclass of MockFoo.
NaggyMock<MockFoo> naggy_foo;    // The type is a subclass of MockFoo.
StrictMock<MockFoo> strict_foo;  // The type is a subclass of MockFoo.

注意: 默认情况下,模拟对象当前是烦人的。将来我们可能会默认将其设置为友好。

模拟类模板

类模板可以像任何类一样进行模拟。

要模拟

template <typename Elem>
class StackInterface {
 public:
  virtual ~StackInterface();
  virtual int GetSize() const = 0;
  virtual void Push(const Elem& x) = 0;
};

(请注意,所有被模拟的成员函数,包括 ~StackInterface() 必须是虚函数)。

template <typename Elem>
class MockStack : public StackInterface<Elem> {
 public:
  MOCK_METHOD(int, GetSize, (), (const, override));
  MOCK_METHOD(void, Push, (const Elem& x), (override));
};

为模拟函数指定调用约定

如果您的模拟函数不使用默认调用约定,您可以通过将 Calltype(convention) 添加到 MOCK_METHOD 的第四个参数来指定它。 例如,

  MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE)));
  MOCK_METHOD(int, Bar, (double x, double y),
              (const, Calltype(STDMETHODCALLTYPE)));

其中 STDMETHODCALLTYPE 由 Windows 上的 <objbase.h> 定义。

在测试中使用模拟

典型的工作流程是

  1. 导入您需要使用的 gMock 名称。 除非它们是宏或另有说明,否则所有 gMock 符号都在 testing 命名空间中。
  2. 创建模拟对象。
  3. (可选)设置模拟对象的默认行为。
  4. 设置对模拟对象的期望(它们将如何被调用?它们将做什么?)。
  5. 执行使用模拟对象的代码; 如果需要,使用 googletest 断言检查结果。
  6. 当模拟对象被销毁时,gMock 会自动验证对其的所有期望是否都已满足。

这是一个例子

using ::testing::Return;                          // #1

TEST(BarTest, DoesThis) {
  MockFoo foo;                                    // #2

  ON_CALL(foo, GetSize())                         // #3
      .WillByDefault(Return(1));
  // ... other default actions ...

  EXPECT_CALL(foo, Describe(5))                   // #4
      .Times(3)
      .WillRepeatedly(Return("Category 5"));
  // ... other expectations ...

  EXPECT_EQ(MyProductionFunction(&foo), "good");  // #5
}                                                 // #6

设置默认行为

gMock 为返回 voidbool、数值或指针的任何函数都有一个内置的默认行为。 在 C++11 中,如果给定类型存在,它还将返回默认构造的值。

要自定义返回类型为 T 的函数的默认行为,请使用 DefaultValue<T>。 例如

  // Sets the default action for return type std::unique_ptr<Buzz> to
  // creating a new Buzz every time.
  DefaultValue<std::unique_ptr<Buzz>>::SetFactory(
      [] { return std::make_unique<Buzz>(AccessLevel::kInternal); });

  // When this fires, the default action of MakeBuzz() will run, which
  // will return a new Buzz object.
  EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber());

  auto buzz1 = mock_buzzer_.MakeBuzz("hello");
  auto buzz2 = mock_buzzer_.MakeBuzz("hello");
  EXPECT_NE(buzz1, nullptr);
  EXPECT_NE(buzz2, nullptr);
  EXPECT_NE(buzz1, buzz2);

  // Resets the default action for return type std::unique_ptr<Buzz>,
  // to avoid interfere with other tests.
  DefaultValue<std::unique_ptr<Buzz>>::Clear();

要自定义特定模拟对象的特定方法的默认行为,请使用 ON_CALLON_CALL 具有与 EXPECT_CALL 类似的语法,但它用于在您不要求调用模拟方法时设置默认行为。 有关更详细的讨论,请参见 了解何时期望

设置期望

请参见模拟参考中的 EXPECT_CALL

匹配器

参见 匹配器参考

行为

参见 行为参考

基数

请参见模拟参考中 EXPECT_CALLTimes 子句

期望顺序

默认情况下,期望可以按任何顺序匹配。 如果必须按给定的顺序匹配某些或所有期望,则可以使用 EXPECT_CALLAfter 子句InSequence 子句,或使用 InSequence 对象

验证和重置模拟

gMock 将在模拟对象被销毁时验证模拟对象的期望,或者您可以更早地执行此操作

using ::testing::Mock;
...
// Verifies and removes the expectations on mock_obj;
// returns true if and only if successful.
Mock::VerifyAndClearExpectations(&mock_obj);
...
// Verifies and removes the expectations on mock_obj;
// also removes the default actions set by ON_CALL();
// returns true if and only if successful.
Mock::VerifyAndClear(&mock_obj);

在使用后验证并清除模拟后,请勿设置新的期望。 在执行模拟的代码之后设置期望具有未定义的行为。 有关更多信息,请参见 在测试中使用模拟

您还可以告诉 gMock 可以泄漏模拟对象,并且不需要验证

Mock::AllowLeak(&mock_obj);

模拟类

gMock 定义了一个方便的模拟类模板

class MockFunction<R(A1, ..., An)> {
 public:
  MOCK_METHOD(R, Call, (A1, ..., An));
};

请参见此 配方,以了解它的一个应用。

标志

标志 描述
--gmock_catch_leaked_mocks=0 不要将泄漏的模拟对象报告为失败。
--gmock_verbose=LEVEL 设置 Google Mock 消息的默认详细级别(infowarningerror)。