目录
- MOCK_METHOD
- mock方法的访问属性
- mock重载函数
- mock模板类
- mock非虚函数
- mock自由函数
- Nice/Strict/Naggy
- mock方法简化参数
- mock具体类的替代方法
- 代理给fake
mock是用来模拟对象,隔离边界的一种测试方法,以便在开发阶段不需要依赖第三方或其他依赖项可以进行独立的测试。
MOCK_METHOD
定义一个普通类,使用MOCK_METHOD 宏生成mock方法。MOCK_METHOD 宏有三到四个参数,前三个参数为函数签名分成的三部分(返回值,函数名,参数),第四个参数为以下一个或多个:
- const:使这个mock方法成为一个const函数,如果重写的函数时const函数,则这个是必须的。
- override:同C++中的override,如果是重写虚函数,建议加上该关键字
- noexpect:如果重写的函数时noexpect,那mock方法也是要加上的
- Calltype(…):
- ref(…):
MOCK_METHOD 形如:MOCK_METHOD(int, my_func, (int x, string y), (const, override));
mock方法的访问属性
不管base class中函数的属性是哪种,mock方法必须都是public。因为这样ON_CALL和EXPECT_CALL可以在mock类外访问。
mock重载函数
重载函数的mock和其他函数没有任何特殊之处
mock模板类
mock非虚函数
mock非虚函数的mock类除了使用MOCK_METHOD 定义的mock函数签名一样外,其他和原类没有任何关系了。
class ConcretePacketStream {
public:
void AppendPacket(Packet* new_packet);
const Packet* GetPacket(size_t packet_number) const;
size_t NumberOfPackets() const;
};
class MockPacketStream {
public:
MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const));
MOCK_METHOD(size_t, NumberOfPackets, (), (const));
};
实际上相当于重新写了和真实类不相关的mock类,只是保持了类函数签名一样。在mock类中可以按实际需要mock函数,不需要mock原类中的所有函数。
mock非虚函数需要在编译期就要决定是哪个对象,这一点不像虚函数。解决这个问题的一种方法是模板化你的代码。在生产代码中使用原类,在测试代码中使用mock类作为模板参数传入(策略模式)
mock自由函数
无法mock一个自由函数(不是类的成员函数都叫自由函数),但是可以通过实现一个接口类,在继承这个接口类的函数中调用这个free functon实现mock它的功能。
class FileInterface {
public:
...
virtual bool Open(const char* path, const char* mode) = 0;
};
class File : public FileInterface {
public:
...
bool Open(const char* path, const char* mode) override {
return OpenFile(path, mode);
}
};
Nice/Strict/Naggy
TEST(...) {
MockFoo mock_foo;
EXPECT_CALL(mock_foo, DoThis());
... code that uses mock_foo ...
}
如果mock函数没有EXPECT_CALL但是被调用了。这种被称为不感兴趣的调用,会有告警信息。如下:
如果要忽略这种信息,可以使用NiceMock<MockFoo>
代替mock_foo
:
NiceMock<MockFoo>
是MockFoo的一个子类。以下方式调用完之后没有uninsterestring信息。
using ::testing::NiceMock;
TEST(test_override, mock_override02) {
NiceMock<MockFoo> foo; // 使用NiceMock<MockFoo>代替MockFoo
EXPECT_CALL(foo, Add(::testing::_))
.Times(1)
.WillRepeatedly(testing::Return(12));
EXPECT_EQ(foo.DoThis(), 12);
}
StrictMock 的用法和NiceMock一样,期望所有的不感兴趣的调用失败。(看输出结果和NiceMock基本一样,不知道有啥区别?)
注意事项:
NiceMock<MockFoo>
andStrictMock<MockFoo>
只作用于使用MOCK_METHOD 宏定义的mock函数中,如果mock函数定义在MockFoo的base类中,NiceMock或StrictMock不会影响它。- 如果MockFoo 类的析构是非虚函数,
NiceMock<MockFoo>
和StrictMock<MockFoo>
可能不会正常工作
mock方法简化参数
mock具体类的替代方法
通过给具体类定义一个父接口类的方式