2012-11-06 61 views
3


我正在寻找C++编码风格的最佳做法,以确保轻松进行单元测试。问题来自于试图为私有数据成员实现一个模拟类。私人数据成员可以通过几种不同的方法访问。到目前为止,我能找到的所有例子都展示了如何编写一个模拟类,而不是如何最好地编写将使用真实和模拟对象的代码。嘲讽私人会员资料

在下面的例子中,我不知道如何从类型MyOtherClass获取mCustom到我的模拟MockMyOtherClass。我怀疑我的做法是错误的,因此也是一个问题。

class MyClass { 
    MyOtherClass mCustom; 
}; 

[编辑]
我去一个编译器指令和增加了一个新的构造函数。

#ifdef UNIT_TESTING 
#include "mock.h" 
#else 
    #include "myotherclass.h" 
#endif 

class MyClass { 
     MyOtherClass mCustom; 
    public: 
     MyClass(MyOtherClass pClass) : mCustom(pClass) {} 
}; 

回答

3

您可以使用几种不同的策略(并根据需要进行组合)。

  1. 如果MyOtherClass提供非常基本的功能,是经过严格测试的本身,然后我通常不与嘲讽理会它。我只是确保在整个项目上运行单元测试时,MyOtherClass会在MyClass之前进行测试。

    class MyClass { 
    private: 
        MyOtherClass mCustom; 
    public: 
        //... 
    }; 
    
  2. 您可以模板化MyClass的,在真正的代码提供MyOtherClass和MyOtherClass的测试代码中的模拟版本。

    template <class T> 
    class MyClass_impl { 
    private: 
        T mCustom; 
    public: 
        //... 
    }; 
    
    typedef MyClass_impl<MyOtherClass> MyClass; // convenience typedef 
    
  3. 您可以将MyOtherClass分成接口类和实现类。 MyClass只存储一个指向接口类的指针,并在实例化时获取对实现的引用。

    class MyClass { 
    public: 
        MyClass(MyOtherClass* aCustom) : mCustom(aCustom) {} 
    private: 
        MyOtherClass* mCustom; 
    public: 
        //... 
    }; 
    
  4. 您可以使用标题的搜索路径玩技巧。为此,您可以在一个单独的目录中创建一个MyOtherClass的模拟版本。然后确保对于单元测试,首先搜索这个单独的目录中的头文件。这使得MyOtherClass的模拟版本首先被找到并且覆盖了MyOtherClass的真实版本。

+0

这些都是可行的解决方案。但是,如果你的数字是4,那么你会被任何开发者烧掉 - 这可能就是为什么它在这个列表中的最后一个。)就我个人而言,我是方法1的粉丝,因为它是最不具侵略性的。 – Matt

+1

在我的情况下,“MyOtherClass”与设备驱动程序对话,所以我需要将其从循环中取出来进行测试。所以选项1不是一个选项。其他人看起来很有趣。 – Jim

+0

@Matt:选项4实际上已被我和其他开发商用于商业项目中。只要采用务实的解决方案,就不会受到危害。 –

0

当我以前遇到这个问题,我分裂MyClass分为两类:(1)一个通用类不参考MyOtherClass,和(2)实现类与MyOtherClass实例化的模板的参数。定义的可见性并不完全相同,但我没有发现它对于任何实际目的都很重要。

然后为了测试,我写了类似MyTestOtherClass的东西,并相应地实例化了MyClass。任何数量的嘲讽技术都可以应用于MyTestOtherClass,并且可能会为了不同的测试目的而生成多个类别。