依赖注入与unique_ptr一起模拟 [英] Dependency injection with unique_ptr to mock
问题描述
我有一个使用Bar类的Foo类。 Bar仅在Foo中使用,而Foo在管理Bar,因此我使用unique_ptr(不是参考,因为我不需要Foo之外的Bar):
I have a class Foo that uses class Bar. Bar is used only in Foo and Foo is managing Bar, therefore I use unique_ptr (not a reference, because I don't need Bar outside of Foo):
using namespace std;
struct IBar {
virtual ~IBar() = default;
virtual void DoSth() = 0;
};
struct Bar : public IBar {
void DoSth() override { cout <<"Bar is doing sth" << endl;};
};
struct Foo {
Foo(unique_ptr<IBar> bar) : bar_(std::move(bar)) {}
void DoIt() {
bar_->DoSth();
}
private:
unique_ptr<IBar> bar_;
};
到目前为止,效果很好。但是,当我要对代码进行单元测试时遇到问题:
So far so good, this works fine. However, I have a problem when I want to unit test the code:
namespace {
struct BarMock : public IBar {
MOCK_METHOD0(DoSth, void());
};
}
struct FooTest : public Test {
FooTest() : barMock{ make_unique<BarMock>() }, out(std::move(barMock)) {}
unique_ptr<BarMock> barMock;
Foo out;
};
TEST_F(FooTest, shouldDoItWhenDoSth) {
EXPECT_CALL(*barMock, DoSth());
out.DoIt();
}
测试失败,因为模拟对象已从Foo进行了转移,并设定了期望值
The test fails because the mock object was transfered fo Foo, and setting an expectation on such mock fails.
DI的可能选项:
- 通过shared_ptr:在这种情况下太多(Bar对象没有在Foo之间共享)
- 通过引用IBar:不是一种选择(Bar不在Foo外部存储,因此Bar创建的对象将被破坏,从而使Foo带有悬空的引用)
- 通过unique_ptr:无法以所提供的方式进行测试
- 通过传递值:是
- by shared_ptr: is too much in this case (Bar object is not shared between Foo any anything else)
- by reference to IBar: isn't an option (Bar is not stored outside Foo, so the Bar object created would be destructed leaving Foo with dangling reference)
- by unique_ptr: isn't testable in the presented way
- by passing by value: isn't possible (copying will occure - same issue as with unique_ptr).
我唯一的解决方案是存储指向BarMock的原始指针在Foo成为BarMock的所有人之前,即:
The only solution I got is to store raw pointer to BarMock before Foo become solely owner of BarMock, i.e.:
struct FooTest : public Test {
FooTest() : barMock{new BarMock} {
auto ptr = unique_ptr<BarMock>(barMock);
out.reset(new Foo(std::move(ptr)));
}
BarMock* barMock;
unique_ptr<Foo> out;
};
没有更清洁的解决方案吗?我是否必须使用静态依赖项注入(模板)?
Isn't there a cleaner solution? Do I have to use static dependency injection (templates)?
推荐答案
毕竟,我最终在所有地方都使用了这种方法:
After all, I ended up using this approach everywhere:
struct FooTest : public Test {
FooTest() : barMock{new BarMock} {
auto ptr = unique_ptr<BarMock>(barMock);
out.reset(new Foo(std::move(ptr)));
}
BarMock* barMock;
unique_ptr<Foo> out;
};
,它与 gtest / gmock
正常工作
这篇关于依赖注入与unique_ptr一起模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!