c++ - 将 googlemock 与非虚拟函数的假 impl 一起使用

标签 c++ unit-testing googletest googlemock

我有一些基于 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 .这个DMockD 无关- 不是从它派生的 - 但它需要与真/假 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/

相关文章:

c++ - CRichEditCtrl::StreamIn 丢失格式

c++ - 使用 getline C++ 获取对象的名称

c# - 单元测试: Raise Event From Nested Type

unit-testing - 编写更好的单元测试的技巧

c++ - CMake 生成的 Xcode 项目无法编译

c++ - 将单词存储在字符串指针中

c++ - 重载矩阵乘法 "* "运算符有问题

javascript - 为什么我的 Jasmine 规范认为我的 Angular 模块未定义

linux - 如何在没有 root 访问权限的情况下在 Ubuntu 上安装 Google Test?

c++ - 在 gmock 的 EXPECT_CALL 中调用 sleep()