代码之家  ›  专栏  ›  技术社区  ›  Kieveli

如何设计C++应用程序,以便模拟对象最容易使用?

  •  3
  • Kieveli  · 技术社区  · 15 年前

    我从未使用测试驱动开发开发开发,也从未使用模拟对象进行单元测试。我总是对不包含应用程序其他方面的简单对象进行单元测试,然后转向只引用已经过单元测试的对象的简单对象。直到最后的“单元”测试是一个组件测试,这一过程才会继续。

    使用什么设计技术来尽可能简单地用模拟对象替换内部类?

    例如,在我的代码中,我将在myWorkerClass中包含myDataClass的头文件。MyDataClass由MyWorkerClass构造,其生命周期与MyWorkerClass绑定。当include是硬连接的时候,如何设置它以便它包含一个模拟的mydataclass?

    3 回复  |  直到 8 年前
        1
  •  2
  •   Alan    15 年前

    您可以尝试调整代码以遵循 (Abstract) Factory Design 模式,在创建模拟对象的单元测试环境中可以使用不同的工厂。

        2
  •  4
  •   Basilevs    8 年前

    初学者的答案是:

    • 在测试类中不要使用 模拟的类型,使用它 接口
    • 而测试提供 模拟对象的另一种实现 界面
    //Common header
    class ObjectInterface {
    public:
      virtual void doThings()=0;
    };
    
    //Release
    class RealObject: public ObjectInterface {
    public:
      virtual void doThings(){
        //Complicated work here
      }
    };
    
    //Testing 
    class MockedObject: public ObjectInterface {
    public:
      virtual void doThings(){
        //Not so complicated work here
      }
    };
    
    //Common header
    class TestedClass {
    public:
      void useObject(ObjectInterface & object) {
        object->doThings();
      }
    };
    
    
    //Unit test
    TestedClass toTest;
    MockedObject mockedObject;
    toTest.useObject(mockedObject);
    
        3
  •  0
  •   Glen    15 年前

    一种方法是不要像那样硬连接你的类。

    使用您的示例:

    MyDataClass将是纯虚拟类。这将至少有2个实现,“真实”实现和模拟实现。

    您的测试代码可以通过有两个构造函数来注入模拟实例,一个使用“MyDataClass”,另一个不使用。有关示例,请参见下面的代码。

    class myWorkerClass {
    public:
        myWorkerClass(myDataClass * dc) : m_dc(dc) {}
        myWorkerClass() : m_dc(new MyRealDataClass()) { }
        ~myWorkerClass { delete m_dc; }
    
    private:
        myDataClass *m_dc;
    }
    

    现在,您可以向所需的MyWorkerClass提供MyDataClass的任何实现。如果您不提供实现,那么您的代码将返回到“真正的”实现上。

    另一种技术是使用工厂模式来实例化对象。您的测试代码可以在工厂上设置一些标志,用于创建MyDataClass的实例,并让它生成一个模拟对象而不是真正的对象。我更喜欢第一种技术,因为它比我更容易使用(另外,我不必为我想测试的所有内容维护工厂类)