eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.24k stars 173 forks source link

Mutable lambda mocking - Not passed by reference #224

Closed helmesjo closed 3 years ago

helmesjo commented 3 years ago

Hi!

Basically what I try to do is to mock with a custom callback which mutates for each invocation, something like this:

When(Method(myMock, func)).AlwaysDo([mutableVar = 0]() mutable
{
    return ++mutableVar;
});

It appears that the callback is not passed-by-reference when the framework invokes it (see TupleDispatcher::invoke<..>(...)), instead a new copy is invoked each time, resulting in this always returning 1, no matter how many times it's called.

This example is just a trivial demonstration. In reality I'm holding an internal buffer and a pointer (stepping forward) is returned. In that case the memory is always garbage once leaving the callback.

Looking at the code the fix appears pretty straight forward, just change this (and related call chain):

static R invoke(std::function<R(arglist &...)> func, const std::tuple<arglist...> &arguments)

to

static R invoke(std::function<R(arglist &...)>& func, const std::tuple<arglist...> &arguments)
                                              ^

Or better yet, use perfect forwarding.

There should be a C++11 equivalent of std::apply available that handles the different cases correctly, I would assume.

helmesjo commented 3 years ago

Made a PR: #225