I have recently ran into the same problem. Since an Asio service's methods (socket's read_some
for example) are generally not virtual, a simple dependency injection is out of question. As far as I understand, there are two possible approaches, both of them are discussed in the Google Mock Cook Book:
High performance dependency injection (duck typing)
Discussed here.
This is the option @ruipacheco had already mentioned in his question.
This option requires templatizing your class, but it introduces the least code overhead.
If, for example, your class uses an Asio tcp socket, constructing an instance of it would look something like:
asio::io_context io_context;
MyClass<asio::ip::tcp::socket> my_class(io_context);
Code to an interface
Discussed here.
This is more or less what @NiladriBose had suggested.
This option requires writing an Asio interface and an Asio concrete adapter, for every service type (socket, timer, etc...)!
Nevertheless, it's the most generic and robust one (and it does not require templatizing your class, as the previous option did).
If, for example, your class uses an Asio tcp socket, constructing an instance of it would look something like:
asio::io_context io_context;
AsioSocket socket(io_context);
MyClass my_class(socket);
Factory enhancement
If your class uses multiple instances of Asio services (multiple sockets, timers, etc...), it would probably be better to create an abstract Asio services factory.
This factory would receive an io_context
in its constructor, and export make_socket
, make_timer
, etc... methods.
Then, constructing an instance of your class would look something like:
AsioFactory asio_factory(io_context);
MyClass my_class(asio_factory);
Finally, in regard to:
And if I go with GoogleMock, why use a class that uses GoogleMock and not my own implementation that does whatever I need?
See this to understand the difference between mock and fake objects. Generally speaking, I think that mock objects require much less effort.
Also see this to figure out how to incorporate a Google mock class with a fake class.