我是gmock的新手,所以我想知道如何将在被测函数中调用的简单C函数存根以进行单元测试。
示例:
int func(int a)
{
boolean find;
// Some code
find = func_1();
return find;
}我搜索过gmock,在我的理解中,gmock没有提供存根简单的C函数的功能,因此我想问一下gmock是否提供了模拟或存根func_1的功能
如果没有,我如何在不更改源代码的情况下手动在测试代码中存根func_1?我正在使用google测试框架进行单元测试。
谢谢。
发布于 2015-08-28 23:30:01
最近我发现自己也遇到了同样的情况。我必须为用C编写的库编写单元测试,这反过来又依赖于同样用C编写的其他库,所以我想使用gmock模拟所有依赖项的函数调用。让我用一个例子来解释我的方法。
假设要测试的代码(库A)调用另一个库lib_x_function()中的函数
lib_a_function()
{
...
retval = lib_x_function();
...
}因此,我想模拟X库。因此,我在文件lib_x_mock.h中编写了一个接口类和一个模拟类
class LibXInterface {
public:
virtual ~LibXInterface() {}
virtual int lib_x_function() = 0;
}
class LibXMock : public LibXInterface {
public:
virtual ~LibXMock() {}
MOCK_METHOD0(lib_x_function, int());
}另外,我创建了一个源文件(比如lib_x_mock.cc),它为实际的C函数定义了一个存根。这将调用mock方法。注意对模拟对象的extern引用。
#include lib_x.h
#include lib_x_mock.h
extern LibXMock LibXMockObj; /* This is just a declaration! The actual
mock obj must be defined globally in your
test file. */
int lib_x_function()
{
return LibXMockObj.lib_x_function();
}现在,在测试库A的测试文件中,我必须全局定义模拟对象,以便它既可以在测试中访问,也可以从lib_x_mock.cc访问。这是lib_a_tests.cc:
#include lib_x_mock.h
LibXMock LibXMockObj; /* This is now the actual definition of the mock obj */
...
TEST_F(foo, bar)
{
EXPECT_CALL(LibXMockObj, lib_x_function());
...
}这种方法非常适合我,我有几十个测试和几个模拟的库。但是,我对创建全局模拟对象是否可以有一些疑问-我在separate question中提出了这个问题,并仍然在等待答案。除此之外,我对这个解决方案很满意。
更新:有关全局对象的问题可以通过创建对象来轻松解决,例如,在测试夹具的构造函数中创建对象,并将指向该对象的指针存储在全局变量中。
然而,也请注意我对这个问题的另一种回答,我刚刚发布了这个问题。
发布于 2018-04-02 17:52:11
这是我对这个问题的另一个回答。在从第一个答案开始的两年里,我逐渐明白GMock根本不是用来模拟C函数的错误框架。在你有很多函数要模拟的情况下,我之前发布的答案实在太麻烦了。原因是GMock使用对象接缝将生产代码替换为模拟代码。这依赖于C语言中不存在的多态类。
相反,要模拟C函数,您应该使用Link Seams,它在链接时用模拟代码替换生产代码。有几个框架可以做到这一点,但我最喜欢的是伪函数框架(FFF)。看看它,它比GMock简单得多。它在C++应用程序中也能很好地工作。
对于感兴趣的人,这里有一个由迈克尔羽毛关于不同类型的接缝的good article。
发布于 2017-01-14 02:07:16
我已经寻找了很长时间来寻找一种解决方案,可以在不更改现有代码的情况下用googleMock模拟遗留的c-函数,最后几天我发现了下面这篇非常棒的文章:https://www.codeproject.com/articles/1040972/using-googletest-and-googlemock-frameworks-for-emb
今天,我使用gmock编写了我的第一个c函数单元测试,并以bcm2835.c库(http://www.airspayce.com/mikem/bcm2835/)中的两个函数为例,用于raspberry Pi编程:这是我的解决方案:我使用的是gcc 4.8.3。在Eclipse和Windows下。注意设置编译器选项-std=gnu++11。
下面是我要测试的函数
int inits(void);
void pinMode(uint8_t pin, uint8_t mode);
int inits(){
return bcm2835_init();
}
void pinMode(uint8_t pin, uint8_t mode){
bcm2835_gpio_fsel(pin, mode);
}包含并定义了使用googleTest / googleMock进行单元测试
// MOCKING C-Functions with GMOCK :)
#include <memory>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
using namespace ::testing;
using ::testing::Return;模拟BCM2835Lib函数
class BCM2835Lib_MOCK{
public:
virtual ~BCM2835Lib_MOCK(){}
// mock methods
MOCK_METHOD0(bcm2835_init,int());
MOCK_METHOD2(bcm2835_gpio_fsel,void(uint8_t,uint8_t));
};创建TestFixture
class TestFixture: public ::testing::Test{
public:
TestFixture(){
_bcm2835libMock.reset(new ::testing::NiceMock<BCM2835Lib_MOCK>());
}
~TestFixture(){
_bcm2835libMock.reset();
}
virtual void SetUp(){}
virtual void TearDown(){}
// pointer for accessing mocked library
static std::unique_ptr<BCM2835Lib_MOCK> _bcm2835libMock;
};实例化模拟的库函数
// instantiate mocked lib
std::unique_ptr<BCM2835Lib_MOCK> TestFixture::_bcm2835libMock;将Mock与c-functions连接的伪库函数
// fake lib functions
int bcm2835_init(){return TestFixture::_bcm2835libMock->bcm2835_init();}
void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode){TestFixture::_bcm2835libMock->bcm2835_gpio_fsel(pin,mode);}从TestFixture创建BCM2835的单元测试类
// create unit testing class for BCM2835 from TestFixture
class BCM2835LibUnitTest : public TestFixture{
public:
BCM2835LibUnitTest(){
// here you can put some initializations
}
};使用googleTest和googleMock编写测试
TEST_F(BCM2835LibUnitTest,inits){
EXPECT_CALL(*_bcm2835libMock,bcm2835_init()).Times(1).WillOnce(Return(1));
EXPECT_EQ(1,inits()) << "init must return 1";
}
TEST_F(BCM2835LibUnitTest,pinModeTest){
EXPECT_CALL(*_bcm2835libMock,bcm2835_gpio_fsel( (uint8_t)RPI_V2_GPIO_P1_18
,(uint8_t)BCM2835_GPIO_FSEL_OUTP
)
)
.Times(1)
;
pinMode((uint8_t)RPI_V2_GPIO_P1_18,(uint8_t)BCM2835_GPIO_FSEL_OUTP);
}结果:)
[----------] 2 tests from BCM2835LibUnitTest
[ RUN ] BCM2835LibUnitTest.inits
[ OK ] BCM2835LibUnitTest.inits (0 ms)
[ RUN ] BCM2835LibUnitTest.pinModeTest
[ OK ] BCM2835LibUnitTest.pinModeTest (0 ms)
[----------] 2 tests from BCM2835LibUnitTest (0 ms total)希望它会有所帮助:) -对我来说,这是一个真正有效的解决方案。
https://stackoverflow.com/questions/31989040
复制相似问题