Search code examples
c++visual-studiovisual-c++googletestgooglemock

GMock removing implicit conversion warning when using ReturnArg


Given the following mock method

MOCK_METHOD2(send, int(const void* pBuffer, size_t szBuffer));

And the following usage

EXPECT_CALL(socketMock, send(_, _))
    .Times(1)
    .WillOnce(ReturnArg<1>());

Will generate a warning in ReturnArg due to the implicit conversion of szBuffer into the return type of int.

Here's an example of code:

#include <cstddef>
#include <cstdint>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

class ISocket {
public:
    virtual int Send(const uint8_t* payload, const std::size_t payloadLength, std::size_t& sentLength) = 0;
};

class SocketMock : public ISocket {
public:
    MOCK_METHOD3(Send, int(const uint8_t*, const std::size_t, std::size_t&));
};

class MySender
{
public:
    static void Ping(ISocket& socket)
    {
        std::size_t bytesSent;
        uint8_t payload[64];
        memset(payload, 0, sizeof(payload));

        socket.Send(payload, sizeof(payload), bytesSent);

        if (bytesSent != sizeof(payload))
            throw std::runtime_error("Socket transmission failed");
    }
};

TEST(SocketSend, ReturnsBytesTransmitted)
{
    SocketMock socket;

    EXPECT_CALL(socket,
        Send(
            ::testing::_, // payload
            ::testing::_, // payload length
            ::testing::_  // return by param, bytes sent
        )).Times(1)
        .WillOnce(::testing::ReturnArg<1>());

    MySender::Ping(socket);

    ::testing::Mock::VerifyAndClearExpectations(&socket);
}

GTEST_API_ int main(int argc, char** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Here's the compiler warning:

googletest\googlemock\include\gmock/gmock-more-actions.h(165): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data (compiling source file TestMain.cpp)

Is there anyway to make GMock use a static_cast to change the return type to eliminate the type conversion warning?


Solution

  • ReturnArg<k> is a Google Mock "action" (reference) that returns the kth argument of the function being mocked. Since in this case, the return type of the function is int and the first argument is of type size_t, a warning about a potentially narrowing warning is generated.

    The easiest way to inject an explicit typecast is to write a custom action:

        ACTION_TEMPLATE(ReturnArgWithTypeCast,
            HAS_2_TEMPLATE_PARAMS(int, k, typename, return_type),
            AND_0_VALUE_PARAMS()) {
            return static_cast<return_type>(::testing::get<k>(args));
        }
    

    The action can be used this way:

    ...
    .WillOnce(ReturnArgWithTypeCast<1, int>())