eranpeer / FakeIt

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

Request: capture invocation arguments by value #96

Closed j-mok closed 2 years ago

j-mok commented 7 years ago

I've run into a case where a stubbed method accepts a by-ref argument which gets destroyed by the time verification kicks in. To my understanding FakeIt records the reference itself as part of invocation, not a copy of the referenced object. This is understandable as some types may be non-copyable. Still it would help a lot if there was syntax for explicitly marking a parameter as record-by-value during stubbing, to avoid situation where verification crashes because the referenced object is no longer there.

Rogiel commented 7 years ago

This seems related to #92 and the little reproducible test case I attached.

j2bbayle commented 7 years ago

I also came across the same issue, and spent a fair amount of time to trace it down to this "reference semantic" problem. Using Do() as a workaround for stubbing is alright but does not help much as verification is concerned, and it would be nice to have a clean way to have a value semantic for call history.

jeduden commented 7 years ago

I am now using do and check the parameters directly in the lambda there. clumsy. but better than not check the params at all.

pjanowski commented 7 years ago

Same issue, same workaround as jeduden. Would be great to fix this or add an option to verify by copy.

estan commented 6 years ago

I think I'm running into this as well, similar to what is described in #92 like @Rogiel mentioned, I get a crash when trying to verify sequences of calls to methods that take const ref arguments.

E.g.

    When(Method(loader, setFileName)).Do([](const QString &s) { qDebug() << s; });
    ...
    Verify(Method(loader, unload) + Method(loader, setFileName).Using("/no/such/file") + Method(loader, fileName)).Once();

It's the .Using here that spoils it. Without that I get no crash, but I want to verify that it was called with exactly "/no/such/file".

Is there any workaround? Aren't a lot of people mocking methods with const ref arguments?

jothepro commented 4 years ago

@jeduden checking parameters directly in the lambda doesn't seem like a super tidy solution, since it mixes test-setup & verification. I ended up assigning the passed reference to a global variable in the Do()-lambda & verifying it afterwards:

std::string passedValue;
When(Method((*mockedObject), mockedFunction)).Do([&passedValue](const std::string& value){
    passedValue = value;
 });
// Then afterwards assert passedValue-content, e.g:
REQUIRE(passedValue == "test");

Thats not a nice workaround at all, just wanted to signal to you that you're not alone out there, @estan ;) Anyone out there with a better idea? :)

malcolmdavey commented 3 years ago

@jothepro Yes that seems to be the only sensible work around. Or store in a vector for multiple invocations, then you need to check all of them ...

Was hoping someone had found a way to implement the copying?

FranckRJ commented 2 years ago

I'll centralize the discussion about this known bug in a new issue: #274