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

时间:2009-09-14 12:33:25

标签: c++ mocking

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

使用哪些设计技术来尽可能简单地用Mock对象替换内部类?

例如,在我的代码中,我将在myWorkerClass中包含myDataClass的头文件。 myDataClass由myWorkerClass构建,其生命周期与myWorkerClass相关联。如何设置它以便在包含硬连接时包含模拟myDataClass?

3 个答案:

答案 0 :(得分:4)

初学者的回答是:

  • 在测试类中不使用实际的 嘲笑的类型,使用它 接口
  • 测试时提供 另一种模拟对象的实现 接口
//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);

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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

使用您的示例:

myDataClass将是一个纯虚拟类。这将至少有2个实现,'真实'和模拟。

您的测试代码可以通过拥有2个构造函数来注入模拟实例,其中一个构造函数采用“myDataClass”而另一个采用“myDataClass”。有关示例,请参阅下面的代码。

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

private:
    myDataClass *m_dc;
}

现在,您可以将myDataClass的任何实现提供给您想要的myWorkerClass。如果您没有提供实现,那么您的代码将依赖于“真正的”实现。

另一种技术是使用Factory模式实例化对象。您的测试代码可以在工厂上设置一些标志,用于创建myDataClass的实例并使其生成模拟对象而不是真实对象。我更喜欢第一种技术,因为它更容易使用(而且我不需要为我想要测试的所有东西维护工厂类)