C++ 除了模拟测试之外,在不额外使用接口的情况下对接口进行编码?

C++ 除了模拟测试之外,在不额外使用接口的情况下对接口进行编码?,c++,c++11,tdd,googletest,gmock,C++,C++11,Tdd,Googletest,Gmock,最近,我一直在尝试在工作中应用TDD,当我需要考虑最好的嘲笑方式时,偶尔会挂断电话。我正在做的工作涉及大量的网络请求和文件系统访问,因此似乎没有任何模仿。从GMOCK文档中,我的理解是,模拟类的最佳选择是通过“编码到接口”,或者通过模板 以下是我关于“编码到接口”的两个主要问题,之后我将举例说明我的问题: 当我目前除了模拟/测试之外没有其他接口的用途时,使用这种方法还有意义吗 所以现在,如果我继续“编码到接口”,我只在模拟/测试时这样做。如果我不是传递那个接口,而是传递我想要模仿的东西(从那个接

最近,我一直在尝试在工作中应用TDD,当我需要考虑最好的嘲笑方式时,偶尔会挂断电话。我正在做的工作涉及大量的网络请求和文件系统访问,因此似乎没有任何模仿。从GMOCK文档中,我的理解是,模拟类的最佳选择是通过“编码到接口”,或者通过模板

以下是我关于“编码到接口”的两个主要问题,之后我将举例说明我的问题:

  • 当我目前除了模拟/测试之外没有其他接口的用途时,使用这种方法还有意义吗
  • 所以现在,如果我继续“编码到接口”,我只在模拟/测试时这样做。如果我不是传递那个接口,而是传递我想要模仿的东西(从那个接口继承的人),我仍然是“向接口编码”吗?我之所以提出这个问题,是因为有时候它更具可读性
  • #1的示例代码

    类的东西{
    bool IsInstalled();//多个文件系统调用,我想模拟这个方法
    };
    bool Install(vector&thingsToInstall)//在“编码到接口”之前
    bool Install(vector&thingsToInstall)//在“编码到接口”之后
    课程内容:公共可安装{
    bool IsInstalled()覆盖;
    };
    II类可安装{
    虚拟布尔已安装()=0;
    };
    
    我感兴趣的模仿行为是是否安装了这些“东西”。基于此,我可能会也可能不会执行网络请求(我已经模拟过了)。因此,与传递“Thing”对象的向量不同,我必须传递一个unique_ptr到IInstallable的向量(我想要模拟的行为/接口)。它看起来很多,所以我只能测试它,甚至不能重用接口。我想我想知道我是否真的在这里“编码到一个接口”,这就是它的方式?另外,您能否详细说明“编写接口代码”在什么时候有意义,什么时候没有意义

    #2的示例代码

    bool安装(vector&thingsToInstall)//来自上面的原始“编码到接口”方法
    
    现在我正在为一个接口编码,考虑到我向接口传递唯一的\u ptr的唯一原因是为了测试它。我有没有理由不把唯一的ptr传递给实现IInstallable接口的“东西”?然后,我仍然可以直接从模拟类的“Thing”继承。这在我的代码中也更具可读性,因为我传递的类型与周围的代码(事物)更相关,而不是更通用的接口。但我是否还在“编写接口代码”?或者我只是完全破坏了“编码到接口”的目的(除了测试)

    这就是最终方法的样子

      bool Install(vector<unique_ptr<Thing>>& thingsToInstall) // Thing still implements IInstallable, so I can mock Thing directly
    
    bool-Install(vector&thingsToInstall)//Thing仍然实现IInstallable,所以我可以直接模拟它
    

    感谢所有花时间阅读本文并作出回应的人!我非常感谢你的帮助。

    我想你的主要问题是关于这个论点:

    它看起来很多,所以我只能测试它,甚至不能重用接口

    但您的
    接口编码示例似乎并不实用。定义一个接口确实需要仔细的设计,而不是“我想模仿它,所以它应该是一个接口”

    那么回到您的例子中,您真正应该考虑的是,<代码>类事物的公共接口是什么,是的,它应该有<代码> BoOL IsSaleLead();代码>但是还有什么

    假设你真正的
    类在实践中有两个功能,那么你将像这样定义你的接口:

    class IThing {
      virtual bool IsInstalled() = 0;
      virtual void DoSomething() = 0;
    };
    
    bool Install(vector<unique_ptr<IThing>>& thingsToInstall);
    
    然后您可以实现它:

    class Thing : public IThing{
      bool IsInstalled() override;
      void DoSomething() override;
    };
    
    然后像这样使用它:

    class IThing {
      virtual bool IsInstalled() = 0;
      virtual void DoSomething() = 0;
    };
    
    bool Install(vector<unique_ptr<IThing>>& thingsToInstall);
    
    bool安装(vector&thingsToInstall);
    
    现在您有机会:

  • 在您的函数中使用
    i字符串
  • 创建
    Thing
    并将
    IThing
    传递给生产代码中的函数
  • 创建
    mokithing
    并将
    IThing
    传递给测试代码中的函数

  • 感谢您抽出时间阅读我的帖子并回复!我的IInstallable实际上还有一个其他的方法和几个变量。我试图让它更像是一个可以“安装”的通用接口。所以在你们的例子中,我是不是把事情做得太具体了(它是可安装的),从而违背了“编码到接口”的目的?当我想到界面时,我想到的是IAnimal&猫/狗。我猜你会如何描述我在这里的目的,因为它只会被用来嘲笑?我想它也会以某种方式使事情脱钩。你能详细说明一下吗?再次感谢你花时间阅读我的文章并作出回应!我在上一次的回复中已经没有字符了,所以我不得不把事情缩短。为了详细说明我所说的“当我想到一个接口时”。。。这只是狗、猫和鱼等所有动物之间的共同点。当你把一个IThing做得如此具体&更少的时候,这是一个公共接口,我明确地计划与多个东西一起重用。更重要的是,我只是将一个接口传递给我的东西,以便我可以测试它,而不是一些可能使用多态性的通用接口(在生产中)。我想我想知道,这是否可以接受,我是否仍在“向接口编码”,你能描述一下它在那一点上完成了什么吗?就像我说的,当你说
    接口
    ,你应该有一个清晰的设计,使事物抽象化,然后你可以在不知道实现细节的情况下使用接口,重新考虑一下你的设计——也许封装整个
    向量
    是一种方法?把单元测试看作是一种改进您的方法