Mocking and dependent injection in C ++

I am trying to do unit testing with googlemock and dependency injection in C ++. Mocks and dependency injections make code testing much easier, but they rely heavily on virtual methods. Although classes in other languages ​​use virtual methods by default, this does not apply to C ++. I use C ++ to create a low-cost system for measuring performance, so just making each individual class inherited from the interface (w / pure virtual methods) is not a desirable option.

In particular, I am having problems with test classes that contain collections of objects, such as:

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_; // ... }; 

To test this class, I could do the following:

 class mock_event { public: MOCK_METHOD0(read, void()); }; TEST(event_manager, test) { event_manager<mock_event> manager; // ... } 

But this will not work, because I can’t set expectations for the mock object, and the mock objects from googlemock are not copied (therefore, the call to std::transform cannot be compiled).

To solve this problem, when testing, I could use pointers instead (i.e. event_manager<mock_event*> ) and pass the factory to the event_manager constructor. But this will not compile due to calls like e.read() (when testing it should be e->read() ).

Then I could use type properties to create a method that, if I gave the link, just returned the link, and if a pointer is given, then look for the pointer (for example, dereference(e).read() ). But that just adds a ton of complexity, and it doesn't seem like a good solution (especially if it's necessary to test all classes containing a collection of objects).

So, I was wondering if there is a better solution for this, or just a mocking and dependent injection is not very suitable for C ++.

+5
source share
1 answer

I assume that you took the appropriate performance measurements with a simple class that emulated a standard use case before deciding that your application could not bear the overhead of dereferencing a pointer to make a virtual function call.

If you read the gmock documentation, they have a “high-performance ridicule” section where they show how to use templates in production code to mimic non-virtual functions.

I think the first rule of the code (production or test) is to keep the code as simple as possible, and therefore I am not convinced of changing the production code using templates to test it (although on the other hand I am fully prepared to use TDD as criticism and design guidelines for my production code).

Thus, it looks like your application needs another mocking structure that allows you to mock at the time of connection, rather than at run time.

Check out cpputest and cppumock ( https://cpputest.imtqy.com/ ), which can simulate both stand-alone C functions and non-virtual C ++ methods.

The price paid by cpputest / cppumock is that it requires more templates than gmock, but it is very good.

+1
source

Source: https://habr.com/ru/post/1258782/


All Articles