我从未开发过使用测试驱动开发,我从未使用模拟对象进行单元测试。我总是对不包含应用程序其他方面的简单对象进行单元测试,然后转向不太简单的对象,这些对象仅引用已经过单元测试的对象。这往往会持续到最终的“单元”测试是组件测试。
使用哪些设计技术来尽可能简单地用Mock对象替换内部类?
例如,在我的代码中,我将在myWorkerClass中包含myDataClass的头文件。 myDataClass由myWorkerClass构建,其生命周期与myWorkerClass相关联。如何设置它以便在包含硬连接时包含模拟myDataClass?
答案 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的实例并使其生成模拟对象而不是真实对象。我更喜欢第一种技术,因为它更容易使用(而且我不需要为我想要测试的所有东西维护工厂类)