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();
}
The test fails because the mock object was transfered fo Foo, and setting an expectation on such mock fails.
Possible options of DI:
- 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).
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)?