Search code examples
c++unit-testinggoogletestgooglemock

Mocking free function gives never called fail on unit test


I am trying to write unit tests for a socket app. I am using the <sys/socket.h> header. In order to test a method, I should mock the socket free functions, so the method is tested in isolation from its dependencies. Here is my attempt, following this instructions:

Test file:

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "path/to/ClientConectionHeader"
#include <sys/socket.h>

using ::testing::AtLeast;

class EstablishSocketInterface {
    public:
    virtual int establishSock(int domain, int type, int protocol) = 0;
};

class EstablishSocket : public EstablishSocketInterface {
    public:
    int establishSock(int domain, int type, int protocol) override {
        return socket(domain, type, protocol);
    }
};

class MockSocket : public EstablishSocket {
    public:
    MOCK_METHOD(int, establishSock, (int domain, int type, int protocol));

};

TEST(ClientConnection, ClientConnectionConstructor) {
    MockSocket mockSocket;
    EXPECT_CALL(mockSocket, establishSock(AF_INET, SOCK_STREAM, 0))
        .Times(AtLeast(1));

    std::string serverIp="127.0.0.1";
    int port=49151;
    ClientConnection client(serverIp,port);
    
}

Header of the class I am testing:

#pragma once

class ClientConnection
{
public:
    ClientConnection(std::string& serverIp_input,int port_input);
  
private:
    int socketfd;
    const char* serverIp;
    int port;

    bool ExitProgram;   
};

Constructor definition:

ClientConnection::ClientConnection(std::string& serverIp_input, int port_input) {
    this->socketfd=socket(AF_INET, SOCK_STREAM, 0);
    if (this->socketfd < 0) {
        perror("socket");
    }
    this->serverIp = serverIp_input.c_str();
    this->port = port_input;
    this->ExitProgram = false;
}

The test fails with the following: Failure

Actual function call count doesn't match EXPECT_CALL(mockSocket, establishSock(2, SOCK_STREAM, 0))...
         Expected: to be called at least once
           Actual: never called - unsatisfied and active
[  FAILED  ] ClienConection.ClientConectionConstructor (0 ms)

The constructor calls the socket() function itself, does not use the mocked one. Dependency injection can work but requires changing the original code. I don't think this is the right approach. Also, to use EXPECT_EQ() to check whether the fields are valued the same as the arguments I pass to the constructor, I need getters, which also requires to be added, but are not needed in the 'production' code.

So how do I gtest my methods as I mock the socket(), send(), recv(), close() functions from the <sys/socket.h> header?

Thanks in advance!


Solution

  • EstablishSocketInterface is never used in the scope of ClientConnection so establishSock is never called (no matter if we consider EstablishSocket or MockSocket. You need to use some form of the technique called 'dependency injection' (e.g. see Dependency injection with unique_ptr to mock). You'll need to wrap all methods (like socket(), send(), recv(), close()) in an interface and use this interface everywhere where you would normally used sys/socket.h directly.

    There's also another technique - the one mentioned in the original question. It requires that all your code is templated so it's not that easy to use. If you insist on it though, then ClientConnection would need to be a templated class with socket as template parameter.