繁体   English   中英

C ++中的模拟和依赖注入

[英]Mocking and dependency injection in C++

我正在努力用C ++中的googlemock和依赖注入进行单元测试。 模拟和依赖注入显着简化了代码测试,但它们严重依赖于虚拟方法。 虽然其他语言中的类默认使用虚方法,但不是C ++的情况。 我正在使用C ++来创建一个低开销的性能测量框架,所以只是让每个类继承一个接口(带有纯虚方法)都不是一个理想的选择。

具体来说,我遇到了测试包含对象集合的类的问题,如下所示:

struct event_info { /* ... */ };

template<typename Event>
class event_manager {
public:
  event_manager(const std::vector<event_info>& events) {
    std::transform(begin(events), end(events),
        std::back_inserter(events_),
        [](const event_info& info) { return Event{info}; });
  }

  void read() {
    for (auto& e : events_)
      e.read();
  }

  // ...

private:
  std::vector<Event> events_;
  // ...
};

为了测试这个课程,我可以做以下事情:

class mock_event {
public:
  MOCK_METHOD0(read, void());
};

TEST(event_manager, test) {
  event_manager<mock_event> manager;
  // ...
}

但这不起作用,因为我无法设置模拟对象的期望,并且来自googlemock的模拟对象不可复制(因此,对std::transform的调用无法编译)。

要解决此问题,在测试时我可以使用指针(例如, event_manager<mock_event*> )并将工厂传递给event_manager构造函数。 但是,由于诸如e.read()之类的调用,它将无法编译e->read()在测试时应该是e->read() )。

然后,我可以使用类型特征来创建一个方法,如果给定引用只返回引用,并且如果给定指针,则取消引用指针(例如, dereference(e).read() )。 但是,这只是增加了大量的复杂性,它看起来不是一个好的解决方案(特别是如果需要进行测试包含对象集合的所有类)。

所以,我想知道是否有更好的解决方案,或者只是模拟和依赖注入不是非常适合C ++的技术。

我假设您在使用一个模拟标准用例的简单类进行了适当的性能测量,然后才决定您的应用程序无法容忍通过指针取消引用的开销来执行虚函数调用。

如果您阅读gmock文档,他们会有一个“高性能模拟”部分,其中显示如何在生产代码中使用模板以允许模拟非虚拟函数。

我认为代码(生产或测试)的第一条规则是保持代码尽可能简单,因此我不相信用模板更改生产代码只是为了能够测试它(尽管另一方面我是完全有利于使用TDD作为我的生产代码设计的批评和指南)。

因此,看起来您的应用程序需要另一个模拟框架,允许在链接时执行模拟,而不是运行时。

查看cpputest和cppumock( https://cpputest.github.io/ ),它可以模拟C独立函数和C ++非虚拟方法。

使用cpputest / cppumock支付的价格是它需要比gmock更多的样板,但它非常好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM