Injeção de dependência com unique_ptr para simulação

Eu tenho uma classe Foo que usa a classe Bar. Bar é usado apenas no Foo e Foo está gerenciando o Bar, portanto, uso unique_ptr (não uma referência, porque não preciso do Bar fora do 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_;
};

Até aí tudo bem, isso funciona bem. No entanto, tenho um problema quando quero testar o código da unidade:

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();
}

O teste falha porque o objeto de simulação foi transferido para o Foo, e a definição de uma expectativa para essa simulação falha.

Possíveis opções de DI:

por shared_ptr: é demais nesse caso (o objeto Bar não é compartilhado entre Foo mais nada)por referência ao IBar: não é uma opção (o Bar não é armazenado fora do Foo, portanto o objeto Bar criado seria destruído, deixando o Foo com referência pendente)por unique_ptr: não é testável da maneira apresentadapassando por valor: não é possível (a cópia ocorrerá - o mesmo problema que com unique_ptr).

A única solução que obtive é armazenar o ponteiro bruto para o BarMock antes que o Foo se torne o único proprietário do BarMock, ou seja:

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;
};

Não existe uma solução mais limpa? Preciso usar injeção de dependência estática (modelos)?

questionAnswers(1)

yourAnswerToTheQuestion