gtest tips summary

Tips

  1. ASSERT_*EXPECT_*

    1. 语义:在检查条件失败时,ASSERT_* 会导致程序异常退出,而 EXPECT_* 会继续执行
    2. 使用场景:
      1. ASSERT_* 适用于断言测试程序的前置条件,例如 server 有没有正常启动,在这种情况下后续的测试都没有意义
      2. EXPECT_* 适用于对后置结果的检查,依次检查实际结果与预期是否相符,如果有多个不符的检查,会依次打印出来而不需要多次执行测试
    3. 更多检查条件见:Assertions References
  2. 断言某个 mock 函数的执行次数:EXPECT_CALL(foo, Bar(_)).Times(n) 断言 foo.Bar 被执行了 n 次

    1. 支持任意次数:AnyNumber()
    2. 支持次数范围:AtLeast(n)>=n
  3. 断言 mock 函数的参数取值:Matcher,参考 Matchers References

    1. 断言字段:Filed(&class::field, m)
    2. 断言容器:
      1. 是非为空 IsEmpty
      2. 是否包含某个元素 Contains
      3. 是否是另一个集合的自己或超集 IsSubsetOf & IsSupersetOf
    3. 断言字符串取值:
      1. 正则 ContainsRegex
      2. 以某些内容起始或结束: StartsWith & EndsWith
  4. 创建 Mock class:MOCK_METHOD(ReturnType, MethodName, (Args ...))

  5. 自定义 Mock function 行为:EXPECT_CALL(...).WillReatly(Invoke(...))

    1. Mock private/protected function 也必须写在 Mock class 的 public section 中,参考
    2. Mock 重载函数时需要指定 override 修饰符,参考
  6. 在测试前后执行逻辑:TEST_F SetUp/TearDown

一个例子

class Foo {
 public:
  ...
 virtual void SetTimeOut(int t);

 protected:
  virtual void Resume();

 private:
  virtual int GetTimeOut();
};

class MockFoo : public Foo {
 public:
  ...
  MOCK_METHOD(bool, Transform, (Gadget* g), (override));

  // The following must be in the public section, even though the
  // methods are protected or private in the base class.
  MOCK_METHOD(void, Resume, (), (override));
  MOCK_METHOD(int, GetTimeOut, (), (override));
  MOCK_METHOD(void, SetTimeOut, (_), (override));
};

TEST(FooTest, Example) {
    Foo foo = new MockFoo();
    // 直接 mock 返回固定结果
    EXPECT_CALL(foo, GetTimeOut()).WillRepeatly(Return(10));

    // mock function 执行自定义逻辑
    EXPECT_CALL(foo, Resume()).WillRepeatly(Invoke([](){ printf("call Resume"); }));

    foo.Resume();

    // 检查 mock function 调用次数
    EXPECT_CALL(foo, Resume()).Times(1);

    EXPECT_EQ(10, foo.GetTimeOut());

    foo.SetTimeOut(10);
    // 检查传递给 mock function 的参数值
    EXPECT_CALL(foo, SetTimeOut(Eq(10))
}