-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow convenient mocking of signals and slots (callback functions) #128
Comments
Maybe I misunderstand, but I think you can already do what you want. Here's a (totally untested) take on how template <typename R, typename ... Args>
struct MockCallback
{
R OnInvoked(Args... args)
{
return InvokedWith(std::tuple<Args>(std::forward<Args>(args)));
}
MAKE_MOCK1(InvokedWith, R(std::tuple<Args>));
auto MakeBind()
{
return [this](auto&& ... args) {
return OnInvoked(std::forward<decltype(args)>(args)...);
}
}
}; By using the indirection to pack all arguments in a tuple, you get around the unknown number of arguments in the mock function. This means you have to place the expectation on Personally I'd prefer to express the type of the callback using a type signature: template <typename>
struct MockCallback;
template <typename R, typename ... Args>
struct MockCallback<R(Args...)>
{
...
}; But that's an unrelated detail. |
Great idea, I will try out what you have. Would be nice to incorporate it into Trompeloeil though, as a contrib component or something. It's a useful utility class. And I would love to have it out of the box on every new project I use your library in! How do the template arguments change if you use the |
The usage of the tuple makes some of the Trompeloeil code break due to ambiguity (tuple vs parameter pack). Here's a live sample you can compile. Error is:
|
That one seems to be a bug. Accepting the tuple by Here's an example: https://gcc.godbolt.org/z/nDHTtx Using the function signature style of template parameter makes for a more natural syntax, IMO. Your example would be: MockCallback<void(int)> slot; |
Created issue #129 for this, in case you want to follow it. |
I have a few interfaces that allow you to subscribe to events that are published. Usually these are implemented with
boost::signals2::signal
. For example (using the Catch2 test library):Above, a callback is registered that sets a captured boolean to
true
if it is invoked. In this test, the goal is to ensure that callback is invoked. The means to which I verify this involves a lot of boilerplate code, which I don't really like. This quickly adds up and makes the test cases difficult to maintain and understand when you have a lot of logic that relies on callback mechanisms like this.If the callback instead were a simple virtual function that was invoked in some interface, I could use a Trompeloeil to verify that function is called. The elegant syntax provided by trompeloeil makes this much easier and better. The cookbook documents a way to mock free functions, but this is very tedious for my use case.
This is just pseudocode, but it would be great to do it like this:
I think it's possible to create a utility class named
MockCallback
that does this, however theTROMPELOEIL_MAKE_MOCK_
macro'snum
parameter must be a literal integer, since the macro does concatenation. So I can't use something likesizeof...(Args)
.Is this a reasonable idea to you? And if so, any ideas on how this can be implemented?
The text was updated successfully, but these errors were encountered: