簡體   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