Aby*_*byx 7 c++ unit-testing dependency-injection raii
在C++中,我经常使用RAII样式的对象使代码更可靠,并在堆栈上分配它们以使代码更高效(并避免使用bad_alloc).
但是在堆栈上创建具体类的对象违反了依赖性反转(DI)原则并且防止模拟该对象.
请考虑以下代码:
struct IInputStream
{
virtual vector<BYTE> read(size_t n) = 0;
};
class Connection : public IInputStream
{
public:
Connection(string address);
virtual vector<BYTE> read(size_t n) override;
};
struct IBar
{
virtual void process(IInputStream& stream) = 0;
};
void Some::foo(string address, IBar& bar)
{
onBeforeConnectionCreated();
{
Connection conn(address);
onConnectionCreated();
bar.process(conn);
}
onConnectionClosed();
}
Run Code Online (Sandbox Code Playgroud)
我可以测试IBar::process
,但我也想测试Some::foo
,而不是创建真正的Connection对象.
当然我可以使用工厂,但它会使代码复杂化并引入堆分配.
另外,我不喜欢添加Connection::open
方法,我更喜欢构造完全初始化和功能齐全的对象.
我会为Connection
类型设置一个模板参数Some
(或者foo
如果将其作为自由函数提取),但我不确定它是否正确(模板看起来像许多人的黑魔法,所以我更喜欢使用动态多态)
你现在正在做的是"强制耦合"RAII类和服务提供者类(如果你想要可测试性,它应该真的是一个接口).解决这个问题:
Connection
成IConnection
ScopedConnection
类,提供RAII例如:
void Some::foo(string address, IBar& bar)
{
onBeforeConnectionCreated();
{
ScopedConnection conn(this->pFactory->getConnection());
onConnectionCreated();
bar.process(conn);
}
onConnectionClosed();
}
Run Code Online (Sandbox Code Playgroud)