Skip to content
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

Cannot setup Return as separate statement #202

Open
Stannieman opened this issue Feb 10, 2020 · 4 comments
Open

Cannot setup Return as separate statement #202

Stannieman opened this issue Feb 10, 2020 · 4 comments

Comments

@Stannieman
Copy link

class IHelper
{
public:
    virtual ~IHelper() = default;
    virtual int MyMethod() const = 0;
}

int main()
{
    Mock<IHelper> mock;
    auto &setup = When(Method(mock, MyMethod));
    setup.Return(1);
    
    return 0;
}

In this example "setup.Return(1);" crashes with read access violation.

It would be quite useful to allow calling Return as a separate statement. Then you can have multiple return values in a vector and do:

vector<int> returnValues{ 1, 2, 3 };
for (const auto returnValue : returnValues)
{
    setup.Return(returnValue );
}

Currently I have to resort to:

size_t index = 0;
vector<int> returnValues{ 1, 2, 3 };
When(Method(mock, MyMethod))
   .AlwaysDo([&]() { return returnValues[index++]; }

I usually set up my mocks in helper methods to share setup code between tests, so that then becomes:

void SetupMyMethod(Mock<IHelper> &mock, const vector<int> &returnValues, size_t &index)
{
    When(Method(mock, MyMethod))
       .AlwaysDo([&]() { return returnValues[index++]; }
}

as you can see there is an additional index reference parameter that you need to keep track of, which is not convenient.

@Stannieman
Copy link
Author

Ok you can do this:

void SetupMyMethod(Mock<IHelper> &mock, const vector<int> &returnValues)
{
    const auto index = std::make_shared<std::size_t>();
    When(Method(mock, MyMethod))
       .AlwaysDo([&, index]() { return returnValues[(*index)++]; }
}

No reference index no more. So this makes this issue a lot less annoying.
Still a nice to have though, but no priority at the moment.

@dmeehan1968
Copy link

I have a similar problem but need to programmatically build the return values from different sources. Sadly it seems that Fakeit has implemented the MethodStubbingProgress return values as temporaries which means they cannot be stored and used over multiple calls. Also, the When() call establishes a new chain of return values, rather than adding to those already existing.

The solution proposed in the last comment really only works if all the return values are known at the time the When() call is made, which doesn't work for my use case. As a result, I'm left with having to build my own array of return values which ultimately means I might as well write my own mocks by subclassing. At least from what I can see of the available API, unless someone else can enlighten me.

Ideally I'd like an API that does (NB: this is over simplified, in reality the progress calls are spread over different parts of the test setup (I'm using Cucumber step_definitions, each providing additional values to describe a sequence).

auto progress = When(Method(mock, myMethod)); // establishes a new return chain
progress.Return(value);
progress.Return(value);
progress.Return(value); // repeat as required

@malcolmdavey
Copy link
Contributor

Wondering if a new chain is ever really useful?

@malcolmdavey
Copy link
Contributor

In general you shouldn't use auto& for return by value. And auto&& is useful here if you don't know the type, but seems this doesn't seem to work either, and there is some subtle logic somewhere that depends on it being in the same statement.

My guess is it's a deep subtle flaw. Might have a deep look if/when I have time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants