Home > Blockchain >  c GMock SetArgReferee as CStringArray
c GMock SetArgReferee as CStringArray

Time:06-01

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)));
  • Related