I have a Foo class that uses the Bar class. Bar is used only in Foo, and Foo controls Bar, so I use unique_ptr (not a link, because I do not 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, it works great. However, I have a problem when I want unit test 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(); }
The test failed because the dummy object was passed to fo Foo and the wait setting with this layout failed.
Possible DI options:
- by shared_ptr: too much in this case (the Bar object is not shared between Foo by anything else)
- by reference to IBar: is not an option (Bar is not stored outside Foo, so the created Bar object will be destroyed, leaving Foo with a dangling link)
- by unique_ptr: not checked by the presented method
- passing by value: impossible (copying will happen - the same problem as with unique_ptr).
The only solution I got is to keep the original pointer to BarMock before Foo becomes the sole 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; };
Is there a cleaner solution? Should I use static dependency injection (templates)?
source share