trompeloeil
trompeloeil copied to clipboard
Any thoughts on mocking coroutines?
Coroutines have made it into C++20 so there are chances they will be more wide-spread.
I have no own ideas (or problems...) yet but I believe there will be demand to mock functions having (at least) co_return / co_yield.
I don't have enough knowledge to have an opinion at this time.
Now I got to them. This approach worked (or similar...)
struct AsyncMockable
{
MAKE_MOCK1(async_func, boost::asio::awaitable<void>(int param));
};
void test()
{
AsyncMockable m;
ALLOW_CALL(m, async_func(_))
.RETURN([]() -> boost::asio::awaitable<void>{ co_return; }());
boost::asio::io_context ctx;
co_spawn(ctx, m.async_func(), boost::asio::detached);
ctx.run();
}
(I just made up an example based on my real case, not sure if it compiles 😊).
In any case, it can work as-is.
What could be improved, is probably a special *_CORO_CALL macro which avoids creating a lambda.
I'm not sure if co_await'ing is needed as an analog to .SIDE_EFFECT macros. Only .CO_RETURN instead of .RETURN. Just adding co_return statement is enough to turn function into a coroutine and could be a good start.
One potential pitfall is that trompeloeil detects void-returning function and allows omitting return for them and requires for non-void functions. For coroutines is is handled by the presence of return_void or return_value in the promise class. But I think a concept could be used to detect this (instead of SFINAE - with coroutines it's C++20).
It took a while, but I just pushed experimental support for coroutines on branch coro_experiment. Details for use is in the ChangeLog and the new tests in test_co_mock.cpp. Documentation is lacking, and error handling is not great. If you want to give it a go, let me know how it works.