我有一些基于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成员的“未定义符号”错误。为了筛选错误并提供可预测的行为,我将在我的测试中为D的方法创建假实现。然而,直到D的方法是虚拟的,我仍然无法使用它与googlemock的所有功能。
我喜欢使用googlemock框架中的WillOnce、AtLeast、WillRepeatedly、Invoke等函数,因为它使单元测试创建更加容易。问题是我不喜欢改变D的界面,把它的方法变成虚拟的。我要为D的方法创建的假实现是否可以使用googlemock函数呢?
注意:我已经考虑过带有模板SUT类的解决方案,但是我想知道是否还有其他解决方案。
发布于 2016-11-04 02:57:37
首先-最好是重新设计你的SUT类,让D通过一些抽象的界面注入。因为我在下面描述的解决办法确实很棘手,所以在将来不容易维护和理解.
如果你要在UT目标中伪造你的D类,那么你可以为D:DMock制作Mock类。这个DMock不会与D相关--不是从它派生出来的--但是它需要与真实/假的D对象配对。
所以-看看这个例子:
创建模拟D接口的DMock (请注意,您应该只模拟公共函数),因为SUT只使用公共函数:
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;
};使用模拟创建D类公共方法的假实现:
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();
}https://stackoverflow.com/questions/40408227
复制相似问题