我需要使用GoogleMock模拟一些类并更改基类实现,以便它实际创建这个模拟的实例。自动生成基类以及其他一些不需要模拟的类,并且所有类都添加在同一个库中。
需要模拟的类是通过工厂创建的,我打算通过它返回子类。我可以“重新链接”这个新库,它已经实现了已经链接的基类吗?
我希望实现的是从被测单元中获取基类的实例,然后将其转换为模拟的基类。
代码示例:
Original.hpp
class Base
{
private:
Base();
public:
virtual ~Base();
static std::shared_ptr<Base> createInstance();
}
Original.cpp
#include "Original.hpp"
...
std::shared_ptr<Base> Base::createInstance()
{
return std::shared_ptr<Base>(new Base());
}
...
Modified.hpp
class Derived : public Base
.....
Modified.cpp
#include "Original.hpp"
#include "Modified.hpp"
...
std::shared_ptr<Base> Base::createInstance()
{
return std::shared_ptr<Base>((Base*) new Derived());
}
所以我希望只要在项目的任何地方通过createInstance实例化Base类,而使用Modified.cpp中定义的createInstance来返回Derived类。
好吧,我想我或多或少了解。如果库已经编译,则无法更改该静态工厂方法的实现。如果您提供自己的实现并尝试将其与现有的lib链接,您将有多个定义(不允许)。你可以做的是在你的应用程序中添加一个层来负责这个Base
对象的创建:
// existing implementation
class Base {
public:
virtual ~Base();
static std::shared_ptr<Base> createInstance() {
return std::shared_ptr<Base>(new Base());
}
private:
Base() {};
};
// new layer, part of your production code
class IYourFactory {
public:
virtual ~IYourFactory() = default;
virtual std::shared_ptr<Base> createInstance() = 0;
};
// new layer, part of your production code
class ProductionFactory: public IYourFactory {
public:
~ProductionFactory() override = default;
std::shared_ptr<Base> createInstance() override {
return Base::createInstance();
}
};
// testing code, you can use GMock to create this class
class MockBase: public Base {
public:
// it's a hack for Base private default constructor
MockBase(): Base(*Base::createInstance()) {}
~MockBase() override = default;
};
// testing code, you can use GMock to create this class
class MockFactory: public IYourFactory {
~MockFactory() override = default;
std::shared_ptr<Base> createInstance() override {
return std::make_shared<MockBase>();
}
};
class YourSystem {
public:
YourSystem(std::shared_ptr<IYourFactory> factory): factory_(factory) {}
bool doSomeThings() {
auto basePtr = factory_->createInstance();
return true;
}
private:
std::shared_ptr<IYourFactory> factory_;
};
当然,如果Base
类具有一些虚拟功能,你可以在你的override
中使用MockBase
,它只会起作用。如果没有,这不是要走的路(你需要为Base
提供的方法创建自己的界面)。
确切的解决方案取决于您在系统中的使用方式以及Base
的界面。