问题
I am trying to mock the system fun ioctl and socket but it is always calling the original definition of system function. Here is the gtest code i have written using gmock.
Please go through the code and help me find what is wrong. Is there a way to mock the system functions using gmock in unit testing. If any please provide me with an example code that mocks system function.
In the test.hpp file
class SystemFun
{
public:
virtual ~SystemFun() {}
virtual int ioctl(int inetSocket, int counters, struct ifreq *device) = 0;
virtual int socket(int domain, int type, int protocol) = 0;
};
class SystemFunMock : public SystemFun
{
private:
static SystemFunMock *oSystemFunMockInstance;
static bool instanceFlag;
public:
virtual ~SystemFunMock() { instanceFlag = false; }
MOCK_METHOD3(ioctl, int(int inetSocket, int counters ,struct ifreq *device));
MOCK_METHOD3(socket, int(int domain, int type, int protocol));
static SystemFunMock *getInstance()
{
if (!instanceFlag)
{
oSystemFunMockInstance = new SystemFunMock();
instanceFlag = true;
}
return oSystemFunMockInstance;
}
};
In the test.cpp file the code
bool SystemFunMock::instanceFlag = false;
SystemFunMock* SystemFunMock::oSystemFunMockInstance = NULL;
int socket(int domain, int type, int protocol)
{
SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();
return oSystemFunMock->socket(domain, type, protocol);
}
int ioctl(int inetSocket, int counters, struct ifreq *device)
{
SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();
return oSystemFunMock->ioctl(inetSocket, counters, device);
}
TEST_F(EtherPortUT, linuxHalCommonTest)
{
SetUp();
SystemFunMock* oSystemFunMock = SystemFunMock::getInstance();
{
InSequence s;
EXPECT_CALL(*oSystemFunMock, ioctl(_,_,_))
.WillOnce(Return(0))
.WillOnce(Return(-1));
EXPECT_CALL(*oSystemFunMock, socket(_,_,_))
.WillOnce(Return(-1));
}
.....
pLNXNetIface->getLinkSpeed( 356, &speed ); // this fun def has 2 ioctl calls but calling the original function.
pLNXNetIface->watchNetLink( iPort ); // this fun def has socket call.
...
}
Definition of the functions getLinkSpeed
bool LinuxNetworkInterface::getLinkSpeed( int sd, uint32_t *speed )
{
struct ifreq ifr;
struct ethtool_cmd edata;
ifr.ifr_ifindex = ifindex;
if( ioctl( sd, SIOCGIFNAME, &ifr ) == -1 )
{
GPTP_LOG_ERROR
( "%s: SIOCGIFNAME failed: %s", __PRETTY_FUNCTION__,
strerror( errno ));
return false;
}
ifr.ifr_data = (char *) &edata;
edata.cmd = ETHTOOL_GSET;
if( ioctl( sd, SIOCETHTOOL, &ifr ) == -1 )
{
GPTP_LOG_ERROR
( "%s: SIOCETHTOOL failed: %s", __PRETTY_FUNCTION__,
strerror( errno ));
return false;
}
...
}
回答1:
You cannot mock a free function. You have to use an interface and call the function using the interface:
bool LinuxNetworkInterface::getLinkSpeed( int sd, uint32_t *speed )
{
...
if(m_pSystemFun->ioctl( sd, SIOCGIFNAME, &ifr ) == -1 )
You must provide some way for LinuxNetworkInterface to get a pointer or reference to SystemFun. In your tests you provide the mock class to LinuxNetworkInterface. In your actual application you provide an actual implementation to LinuxNetworkInterface.
It seems you are on the right track. But the interface SystemFun is not just for testing but is also to be used in the application.
来源:https://stackoverflow.com/questions/57950808/with-googletest-i-am-not-able-to-mock-system-function