如何在函数内GMOCK一个函数?

时间:2017-02-28 14:13:57

标签: c++ unit-testing googletest googlemock gmock

我有一个function1,其中调用了函数2。我必须只模拟function2,每当我调用function1它应该调用function1的实际实现和function2的模拟实现。请帮助我

Display.cpp

    #include "Display.h"
int DisIp::getip()
{

return 5;

}
int  DisIp::display()
{
        Addition obj;
        int ip=obj.getip();
    return ip;
}

Display.h

class DisIP
{
public:
    int display();
        int getip();
};

GMOCK文件

#include <limits.h>
#include "gmock.h"
#include "gtest.h"
#include "Display.h"
#include <string>
using namespace std;
using ::testing::AtLeast;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Gt;
using ::testing::Return;
using testing::ReturnPointee;
using ::testing::Invoke;
class MyInterface{
public:

    virtual int display() = 0;
    virtual int getip()=0;
};

class MockInter : public MyInterface
{
public:
MockInter()
{
        ON_CALL(*this, getip()).WillByDefault(Invoke(&this, &MockInter::getip));
        ON_CALL(*this, display()).WillByDefault(Invoke(&real, &Addition::display));
}
MOCK_METHOD0(display,int());
MOCK_METHOD0(getip,int());
DisIp real;
};


class DisplayTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
  }

  virtual void TearDown() {
    // Code here will be called immediately after each test
    // (right before the destructor).
  }
};

TEST_F(DisplayTest,ip){
        MockInter mock;
//EXPECT_EQ(1,mock.display());
EXPECT_EQ(1,mock.getip());
}

2 个答案:

答案 0 :(得分:1)

您的设计遭受破坏Single Responsibility Principle

显示和获取IP是两个不同的职责。它甚至会在您DisIp::display()的实施中显示 - 您从所谓的Addition obj获得IP。当您修复此设计错误时 - 您的单元测试变得更加容易和直接。但重要的是要说UT只是这里的症状,糟糕的设计是一种疾病。

它看起来如何:

class IIpProvider
{
public:
  virtual ~IIpProvider() = default;
  virtual int getIp() = 0;
};

class DispIp
{
public:
    DispIp(IIpProvider& ipProvider) : ipProvider(ipProvider) {}
    int display()
    {
       int ip=ipProvider.getIp();
       //...
       return ip;
    }
private:
   IIpProvider& ipProvider;
};
然后你的模拟:

class IpProviderMock : public IIpProvider
{
public:
  MOCK_METHOD0(getIp, int());
};

你的测试:

class DispIpTest : public ::testing::Test
{
protected:
   IpProviderMock ipProviderMock;
   DispIp objectUnderTest{ipProviderMock}; // object-under-test must be connected to object doubles (like mocks)
};
TEST_F(DispIpTest, shallUseProvidedIpToDisplay)
{
    using namespace testing;
    auto SOME_IP = 7;
    EXPECT_CALL(ipProviderMock, getIp()).WillRepeatedly(Return(SOME_IP));
    //...
    ASSERT_EQ(SOME_IP, objectUnderTest.display());
}

在您的原始测试中 - 主要问题还在于您的模拟对象没有以任何方式连接到您测试的对象。

如果你不喜欢(不能)改变你的设计(我真正的建议)你必须使用名为partial mocking的技术

在你的情况下 - 它会是这样的:

class DisIP
{
public:
    int display();
    virtual int getip(); // function for partial mocking must be virtual
};
class DisIPGetIpMock : public DisIP
{
public:
      MOCK_METHOD0(getIp, int());
};
class DispIpTest : public ::testing::Test
{
protected:
   DisIPGetIpMock objectUnderTest; 
};

TEST_F(DispIpTest, shallUseProvidedIpToDisplay)
{
    EXPECT_CALL(objectUnderTest, getIp()).WillRepeatedly(Return(SOME_IP));
    ...
    ASSERT_EQ(SOME_IP, objectUnderTest.display());
}

答案 1 :(得分:0)

如果可以帮助您,您可以使用Cutie库来模拟C函数GoogleMock样式。
回购中有完整的样本,但只是一种味道:

INSTALL_MOCK(fclose);
CUTIE_EXPECT_CALL(fclose, _).WillOnce(Return(i));