问题
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