-
Notifications
You must be signed in to change notification settings - Fork 175
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
Verify methods with parameters passed by reference #31
Comments
Well, that's an interesting corner case.
Thus, you can only verify with the original reference at the moment of invocation. The following line will work with your example: Verify(Method(mock, foo).Using(i), Method(mock, foo).Using(i)).Once(); Do you think we need a special behavior for reference of scalar types? |
You are right, I'm really in a corner case. Maybe I should use Do/AlwaysDo methods to test this corner case. On Thu, Aug 13, 2015 at 2:49 PM, eranpeer notifications@github.com wrote:
Bertrand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . |
For example: struct SomeInterface {
virtual ~SomeInterface() {}
virtual int foo(int&) = 0;
};
std::vector<int> values;
Mock<SomeInterface> mock;
When(Method(mock, foo)).AlwaysDo([&](int& i)
{
values.push_back(i);
return 1;
});
auto &si = mock.get();
auto i = 0;
si.foo(i);
++i;
si.foo(i);
ASSERT_EQUAL(0, values[0]);
ASSERT_EQUAL(1, values[1]); |
That's what I am ending with. I think it's the way to do it. Thanks a tonn for your library. I am migrating from HippoMocks and I have to say that my tests are fare On Thu, Aug 13, 2015 at 3:41 PM, eranpeer notifications@github.com wrote:
Bertrand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . |
Thank's for the feedback. |
I also just ran into this case but with a const & to a temporary on the callers stack. Verifying the Method with Using in this case leads to undefined behaviour. I agree with the assessment that you can't always take a copy. I'm wondering if you can make calling Using an error in these cases to avoid potential segfaults? It would be pretty clever to detect if a type is copy constructable and take a copy in that case too, but that's going above and beyond. Also liking fakeit so far. Thanks! |
I have some idea of how to fix this and I'm working on a POC (Proof Of Concept). |
Any news on this? I'm currently having to hack together custom call sequence recorders for methods with |
Run into the same problem unit testing some 3d math code. E.g. a function that does a vec3 + vec3 and passes the local result to a mock class by const&. This scenario is too common for us so without a clean solution we have to stick with google mock (which solves this problem by defining your verifys before the invocation and capturing/matching the arguments at call time). Apart from that this library was working really good. |
any news on this issue ? |
I don't know why you call this a corner case. The only resort seems to be the suggestion @eranpeer made in #31 (comment) , but that takes away the whole point of using |
It looks like issue still persists. |
I've done a small modification to the library that solves this issue for me. This modification doesn't cover all the cases but it works perfect for my project. When you open single-header fakeit.hpp you can see something like this in first few lines of code: template< class T > struct tuple_arg { typedef T type; };
template< class T > struct tuple_arg < T& > { typedef T& type; };
template< class T > struct tuple_arg < T&& > { typedef T&& type; };
template<typename... arglist>
using ArgumentsTuple = std::tuple < arglist... > ; Just replace this code with the following: template< class T > struct tuple_arg { typedef typename std::remove_reference<T>::type type; };
template<typename... arglist>
using ArgumentsTuple = std::tuple < typename std::remove_reference<arglist>::type... >; The idea behind this modification is the following. |
@eranpeer Should this really be closed? Is @otterovich solution something that can be built on? As previously mentioned, without reliably being able to verify arguments passed to a mock one is severely limited. |
I'm not sure if this solution is something one can build upon. I just stumbled over this bug while trying out FakeIt. I believe the current solution might fail to compile in cases the argument is not copy-constructible. Also, it would be great if this workaround would be integrated into master/tagged branch. |
This modification does inhibits to mock methods that receive const-ref arguments:
Error message when compiling with gcc7
(see the mismatched types const S& and const S line. I believe this is due to the std::remove_reference proposal. Any workarounds? |
I'm using the following workaround: class I {
public:
virtual void test(const std::string& d) = 0;
};
class IFix : public I {
public:
virtual void testF(std::string d) = 0;
};
using namespace fakeit;
TEST_CASE("blaat") {
Mock<IFix> mock;
When(Method(mock, testF)).AlwaysReturn();
When(Method(mock, test)).AlwaysDo(std::bind(&IFix::testF, &mock.get(), std::placeholders::_1));
mock.get().test("123");
mock.get().test("456");
Verify(Method(mock, testF).Using("123"), Method(mock, testF).Using("456"));
} Basically, you forward the method using references to a call that does not use them. Than build the test on that method. Not super pretty, but at least you don't have to change production code or fakeIt itself. The *Fix interface can just exist in the test code. Note that both It's something... |
This makes fakeit nearly useless for me, the whole point of having a mock library is that I don't have to write the mock by hand. Now I have to write a wrapper that defines a place where to store the argument, define the mock method that copy the ref argument in there and triggers the fakeit mock so that I can call verify. I'll stop using faking when I have a bit of time to switch to something else. |
Any progress on this? Does seem like quite more than a corner case, and mostly because the verify logic is done after the invocation step, not at the same time. Yes, strings are a big issue here. Also who are the main maintainers of this now? |
I guess this is the reason why Google Mock requires expectations to be set before executing the methods that are supposed to call the mock and not after the fact. |
I'm planning an opt in fix/change to support this, to enable copying of parameters. |
I ran into the same issue today. It caused a SEGFAULT, thanks to debug runtime checks. Unfortunately, it took me some debugging to figure out the root cause. I'd prefer if this footgun wasn't possible, as @coombez suggested:
My workaround is to patch fakeit's Furhtermore, I believe that this problem is not solvable: Besides reference parameters, one may use non-owning views (e.g. That's probably the reason, why with gMock you have to make the assertion upfront (as @dirkharbinson mentioned):
|
Yeah, it's a known issue, as you have seen I tried to centralize the discussion about it here: #274. |
Hello,
We have interfaces with methods that take parameters by reference.
Stubing such methods seem to work but when trying to Verify invocations, I got troubles.
I got the following output:
All the invocations seem to be done with last value of the parameter.
Is there a way to indicate to FakeIt that this parameter should be treated as by copy. Here we only pass it by reference for optimization purpose.
Thanks for your help
Sincerely
Bertrand
The text was updated successfully, but these errors were encountered: