依赖注入与unique_ptr一起模拟 [英] Dependency injection with unique_ptr to mock

查看:91
本文介绍了依赖注入与unique_ptr一起模拟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆