我有一些基于 googlemock 框架的单元测试的遗留代码。当我尝试使用一些新场景扩展单元测试时,我遇到了以下问题:
class D
{
public:
void pubMethod1();
int pubMethod2();
// There are pretty much non-virtual methods, both public and private
...
protected:
uint method3();
void method4();
...
// Some class members are here
};
class SUT
{
public:
...
protected:
D _dep;
};
应测试 SUT 类(被测软件),其实现在文件
sut.cpp
中定义. SUT 依赖于 D 类,其实现在文件 d.cpp
中.为了减少链接器依赖性,我不想添加 d.cpp
到测试,所以当我链接测试时,对 D 的成员有很多“ undefined symbol ”错误。为了消除错误并提供可预测的行为,我将为我的测试中的 D 方法创建假实现。但是,在 D 的方法是虚拟的之前,我仍然无法将它与 googlemock 的所有功能一起使用。我喜欢使用 googlemock 框架中的 WillOnce、AtLeast、WillRepeatedly、Invoke 等功能的想法,因为它使单元测试的创建更容易。问题是我不喜欢改变 D 的接口(interface),把它的方法变成虚拟的方法。是否可以将 googlemock 函数与我将为 D 的方法创建的假实现一起使用?
注意:我已经考虑过使用模板化 SUT 类的解决方案,但是我想知道是否存在其他解决方案。
最佳答案
首先 - 最好的办法是重新设计您的 SUT 类以通过一些抽象接口(interface)注入(inject) D。因为我在下面描述的解决方法非常棘手 - 所以将来维护和理解并不容易......
如果您要在 UT 目标中制作 D 类的假实现 - 那么您可以为 D 制作 Mock 类:DMock
.这个DMock
与 D
无关- 不是从它派生的 - 但它需要与真/假 D 对象配对。
所以 - 见例子:
创建 DMock - 模仿 D 接口(interface)(请注意,您应该只模拟公共(public)函数 - 因为您的 SUT 只使用公共(public)函数):
class DMock
{
public:
MOCK_METHOD0(pubMethod1, void ());
MOCK_METHOD0(pubMethod2, int ());
};
将您的真实(但假的)D 对象与 DMock 对象配对 - 如下所示:
class DMockRepo
{
public:
// for UT
void addMockToUse(DMock* dMock) { freeMock.push_back(dMock); }
// for implementing D fake methods
DMock& getMock(D* original)
{
// TODO: use more sophisticated way to add mock to map...
if (not usedMock[original])
{
usedMock[original] = freeMock.front();
freeMock.pop_front();
}
return *useddMock[original];
}
static DMockRepo& getInstance() { return instance; } //singleton
private:
DMockRepo() {} // private
static DMockRepo instance;
std::map<D*,DMock*> usedMock;
std::deque<DMock*> freeMock;
};
使用 mock 创建 D 类公共(public)方法的假实现:
void D::pubMethod1()
{
DMockRepo::getInstance().getMock(this).pubMethod1();
}
//
非公开方法是无关紧要的——所以随心所欲……
并使用 DMockRepo 为您的 D 对象设置期望:
TEST(Usage,Example)
{
DMock dMock;
DMockRepo::getInstance().addMockToUse(&dMock);
SUT sut; // you should know how many D objects SUT needs - I assume just one
EXPECT_CALL(dMock, pubMethod1());
sut.doSomethingThatCallsDpubMethod1();
}
关于c++ - 将 googlemock 与非虚拟函数的假 impl 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40408227/