将 googlemock 与非虚拟函数的假实现一起使用

2024-03-08

我有遗留代码和一些基于 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 接口、将其方法变成虚拟方法的想法。是否可以使用googlemock功能与虚假的实施我要为D 创建方法吗?

注意:我已经考虑过使用模板化 SUT 类的解决方案,但是我想知道是否存在其他解决方案。


首先 - 最好的方法是重新设计您的 SUT 类,以通过某些抽象接口注入 D。因为我在下面描述的解决方法确实很棘手 - 所以将来不太容易维护和理解......


如果您要在 UT 目标中伪造 D 类的实现 - 那么您可以为 D 制作 Mock 类:DMock. This DMock不会与D- 不是从它派生 - 但它需要与真/假 D 对象配对。

所以 - 请看示例:

创建 DMock - 模仿 D 接口(请注意,您应该仅模拟公共函数 - 因为您的 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();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 googlemock 与非虚拟函数的假实现一起使用 的相关文章

随机推荐