我无法解决这个问题:我有一个名为MyClass的类,该类具有MyUsedClass类型的私有(private)成员。为了创建单元测试,我有一个MyUsedClass的模拟(模拟)版本。我想用模拟的MyUsedClass私有(private)成员或MyUsedClass的真正私有(private)成员动态调用MyClass。因为我想动态调用它,所以无法使用#defines和#ifdefs。
基本上我想做这样的事情:
class MyClass {
public:
MyClass(bool mock = false) {}; // Default bool to false.
~MyClass(void) {};
void DoSomething(void) { /* Do something with MyUsedObject here... */ };
void DoMore(void);
...
private:
if (mock) {
MyUsedClassMock MyUsedObject;
} else {
MyUsedClassReal MyUsedObject;
}
};
MyClass MyObject; // Create default instance with real MyUsedObject.
MyClass MyObject(true); // Create instance with the mock MyUsedObject.
但是,这当然是行不通的,因为一个类的定义中的if语句无法执行。
另一种方法是使用多态性并创建基类,真实类和模拟类。基类将具有所有功能的所有实现,并且通过选择调用MyClass的真实版本或模拟版本,我可以选择MyUsedObject的类型。
class MyClassBase {
public:
MyClassBase(void) {};
~MyClassBase(void) {};
void DoSomething(void) { /* Do something with MyUsedObject here... */ };
void DoMore(void);
...
private:
// No MyUsedObject in the Base class.
};
class MyClassReal : public MyClassBase {
public:
MyClassReal(void) {};
~MyClassReal(void) {};
private:
MyUsedClassReal MyUsedObject; // Here is MyUsedObject created, but then "Real".
};
class MyClassMock : public MyClassBase {
public:
MyClassMock(void) {};
~MyClassMock(void) {};
private:
MyUsedClassMock MyUsedObject; // Here is MyUsedObject created, but then "Mock".
};
MyClassReal MyObject; // Create instance with the real MyUsedObject.
MyClassMock MyObject; // Create instance with the mock MyUsedObject.
不幸的是,由于MyClassBase函数实现对MyUsedObject还一无所知,所以这也不起作用。一种想法是用来在基类中创建虚拟MyUsedObject,但是这里的问题是基类尚不知道对象的类型(真实或模拟)。同样,在数据声明中不允许使用“虚拟”,因此无论如何我都会再次遇到更多错误。
我在这里想念什么?
最佳答案
多态方法是必经之路。但是,您必须提出不同的建议:
class MyUsedClass { }; // the base class, having (pure?) virtual functions
class MyUsedClassReal : public MyUsedClass { }; // provides real functionality
class MyUsedClassMock : public MyUsedClass { }; // mocks the functionality
派生类将提供实际场景和模拟时特别需要的实现。您自己的类现在将动态地使用一个或另一个:
class MyClass
{
public:
MyClass(bool mock = false)
~MyClass(void) {};
void doSomething();
private:
std::unique_ptr<MyUsedClass> myUsedObject;
};
MyClass::MyClass(bool mock)
: myUsedObject(mock ? new MyUsedClassMock() : new MyUsedClassReal())
{ }
void MyClass::doSomething() { /* use the pointer! */ };
如果遵循StoryTeller的提示(“依赖注入(inject)”),则会将对象作为参数传递给构造函数,而不是在内部创建它,这可能是更可取的:
MyClass::MyClass(std::unique_ptr<MyUsedClass> object)
: myUsedObject(std::move(object))
{ }
也有一个
std::unique_ptr
作为参数,这显然表明MyClass
将获取所提供对象的所有权(为此是一个接收器);这适用于您的示例,而不是“总是执行”规则,它取决于用例,在其他情况下,共享指针(成员和参数)可能更合适。