Mam klasę Foo, która używa paska klasy. Bar jest używany tylko w Foo Foo i zarządza bar, dlatego używam unique_ptr (nie odwołanie, ponieważ nie muszę Bar poza Foo):Wstrzyknięcie zależne z unique_ptr na próbę
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_;
};
tej pory tak dobrze, to działa prawidłowo. Jednak mam problem, gdy chcę do badanej jednostki kod:
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();
}
test zakończy się niepowodzeniem, ponieważ obiekt został przeniesiony mock fo Foo i ustawienie oczekiwanie na takie makiety zawiedzie.
Możliwe opcje DI:
- przez shared_ptr: jest zbyt wiele w tym przypadku (object Bar nie jest dzielona pomiędzy Foo żadnego cokolwiek innego)
- przez odniesienie do IBAR: nie jest rozwiązaniem (Pasek nie jest przechowywany poza Foo, więc utworzony obiekt Baru zostanie zniszczony, pozostawiając Foo z wiszącym odwołaniem)
- przez unique_ptr: nie można przetestować w przedstawionym sposobie
- przez przekazanie wartości: nie jest możliwe (kopiowanie będzie occure - ten sam problem, co w przypadku unique_ptr).
Jedynym rozwiązaniem mam jest przechowywanie surowego wskaźnik BarMock przed Foo stać wyłącznie właściciel BarMock, tj .:
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;
};
Czy nie czystsze rozwiązanie? Czy muszę używać iniekcji statycznej (szablony)?
Możesz być zainteresowany w czytaniu [ta odpowiedź] (http://stackoverflow.com/questions/7616475/can-google-mock-a-method-with-a-smart-pointer -return-type/11548191 # 11548191). –
@ πάντα ῥεῖ: dziękuję za link. Już to widziałem i działa dla metod, które biorą unique_ptr jako parametr - ale nie jestem pewien, czy można zastosować to podejście dla konstruktorów. – Quarra