Using c 11 with MFC, and trying to create some unit tests with gtest 1.7, I've encountered a problem. I want to mock a nasty method without changing the declaration or the definition of the method below.
virtual bool getValue(CStringArray& valueOut) const;
Mocking is simple, MOCK_CONST_METHOD1(getValue,bool(CStringArray&));
will do this for me. However, using in the test case, I cannot make it work.
The relevant part from the test case:
CStringArray localArray;
localArray.Add("Only One Element");
EXPECT_CALL(object, getValue(_)).WillOnce(DoAll(SetArgReferee<0>(localArray), Return(true)));
This gives me a compilation error, because CStringArray
(as derived from CObject
) is not-copyable, not-movable object. My question is,
How can I alter the return array using only mock functions?
I know that I can create a hybrid mock, with a real function building up the array, but it would be harder for me to add custom elements to each test case. Something like:
struct MockNastyObject : public NastyObject {
MOCK_CONST_METHOD1(getValueMock, bool(CStringArray&));
virtual bool getValue(CStringArray& arr) const override{
arr.Add("Element1");
getValueMock(arr);
}
};
This approach could work, as I can set expectation for the getValueMock
and alter the array with the non-mock method.
CodePudding user response:
One approach would be to create a gmock action as seen below.
First, you need to create a helper method, that will populate your array when setting the expectation (out of class or test case as mentioned in the documentation). Then set a proper EXPECT_CALL
to make it work.
struct MockNastyObject : public NastyObject {
MOCK_CONST_METHOD1(getValue, bool(CStringArray&));
};
ACTION_P(AddParamToCArray, param) { arg0.Add(param); }
TEST(testOne, populateTest)
{
MockNastyObject myMock;
EXPECT_CALL(myMock, getValue(_)).WillOnce(DoAll(
WithArg<0>(AddParamToCArray("First element")),
WithArg<0>(AddParamToCArray("Second element")),
Return(true)));
...
}
As you can see, this can be useful not only to CStringArray
but any container, that supports Add
.
The initial question was about SetArgReferee
although the solution does not use it.
Also, another approach could be useful as well.
CodePudding user response:
I do not know what you want to achieve - the fist code snippet is the assignment, the second code snippet is the element addition. As for the second one, it can be done with a lambda w/o a custom specialized action:
CStringArray localArray;
localArray.Add("Only One Element");
EXPECT_CALL(object, getValue(_)).WillOnce(DoAll(
WithArg<0>([&localArray](CStringArray& a) { a.Add(localArray[0]); }),
Return(true)));
Or simplified w/o the localArray
:
EXPECT_CALL(object, getValue(_)).WillOnce(DoAll(
WithArg<0>([](CStringArray& a) { a.Add("Only One Element"); }),
Return(true)));