Google Mock : Setting argument in EXPECT_CALL

Gemma Morriss picture Gemma Morriss · Feb 10, 2016 · Viewed 10.1k times · Source

I am trying to set a class member function parameter value in Google Mock, but I get build errors and I simply don't understand what is going on. Would it be possible for someone to explain please.

The function prototype is:

virtual int recv( Socket socket
                , char *buffer
                , int bufferLength
                , int flags ) = 0;

I am trying to test it using:

TEST_F( IPV4SocketTests, Read_SockErr_ok )
{
    Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
    char *rcvBuffer = "testingRcvWorks";

    EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        testing::SetArgPointee<1>( rcvBuffer ),
        testing::Return( strlen( rcvBuffer ) ) ) );

The error I am getting is regarding conversion from std::get.

Answer

Marko Popovic picture Marko Popovic · Feb 10, 2016

The problem is that rcvBuffer is a pointer. That is why you must dereference it when setting the pointee. Here is how your EXPECT_CALL should look:

EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        testing::SetArgPointee<1>( *rcvBuffer ),
        testing::Return( strlen( rcvBuffer ) ) ) );

EDIT:

This is the approach I've used in my projects to mock returning a char array through a pointer used as argument. First, you need to create a custom action that will copy the contents of the buffer (you cannot use SetArrayArgument in this case):

ACTION_TEMPLATE(SetArgNPointeeTo, HAS_1_TEMPLATE_PARAMS(unsigned, uIndex), AND_2_VALUE_PARAMS(pData, uiDataSize))
{
    std::memcpy(std::get<uIndex>(args), pData, uiDataSize);
}

Then, in a test use it like this:

Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
char rcvBuffer[] = "testingRcvWorks";
size_t bufferSize = sizeof("testingRcvWorks");

EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        SetArgNPointeeTo<0>(std::begin(rcvBuffer), bufferSize),
        testing::Return( strlen( rcvBuffer ) ) ) );