如何在函数内 GMOCK 一个函数?
How to GMOCK a function within function?
我有一个函数 1,其中调用了函数 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());
}
您的设计有问题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());
}
您可以使用 Cutie 库模拟 C 函数 GoogleMock 样式,如果这对您有帮助的话。
回购中有一个完整的样本,但只是一个味道:
INSTALL_MOCK(fclose);
CUTIE_EXPECT_CALL(fclose, _).WillOnce(Return(i));
我有一个函数 1,其中调用了函数 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());
}
您的设计有问题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());
}
您可以使用 Cutie 库模拟 C 函数 GoogleMock 样式,如果这对您有帮助的话。
回购中有一个完整的样本,但只是一个味道:
INSTALL_MOCK(fclose);
CUTIE_EXPECT_CALL(fclose, _).WillOnce(Return(i));