首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >gmock可以用于存根C函数吗?

gmock可以用于存根C函数吗?
EN

Stack Overflow用户
提问于 2015-08-13 21:02:27
回答 6查看 28K关注 0票数 19

我是gmock的新手,所以我想知道如何将在被测函数中调用的简单C函数存根以进行单元测试。

示例:

代码语言:javascript
运行
复制
int func(int a)
{
  boolean find;
  // Some code
  find = func_1();
  return find;
}

我搜索过gmock,在我的理解中,gmock没有提供存根简单的C函数的功能,因此我想问一下gmock是否提供了模拟或存根func_1的功能

如果没有,我如何在不更改源代码的情况下手动在测试代码中存根func_1?我正在使用google测试框架进行单元测试。

谢谢。

EN

回答 6

Stack Overflow用户

发布于 2015-08-28 23:30:01

最近我发现自己也遇到了同样的情况。我必须为用C编写的库编写单元测试,这反过来又依赖于同样用C编写的其他库,所以我想使用gmock模拟所有依赖项的函数调用。让我用一个例子来解释我的方法。

假设要测试的代码(库A)调用另一个库lib_x_function()中的函数

代码语言:javascript
运行
复制
lib_a_function()
{
   ...
   retval = lib_x_function();
   ...
}

因此,我想模拟X库。因此,我在文件lib_x_mock.h中编写了一个接口类和一个模拟类

代码语言:javascript
运行
复制
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引用。

代码语言:javascript
运行
复制
#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:

代码语言:javascript
运行
复制
#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中提出了这个问题,并仍然在等待答案。除此之外,我对这个解决方案很满意。

更新:有关全局对象的问题可以通过创建对象来轻松解决,例如,在测试夹具的构造函数中创建对象,并将指向该对象的指针存储在全局变量中。

然而,也请注意我对这个问题的另一种回答,我刚刚发布了这个问题。

票数 24
EN

Stack Overflow用户

发布于 2018-04-02 17:52:11

这是我对这个问题的另一个回答。在从第一个答案开始的两年里,我逐渐明白GMock根本不是用来模拟C函数的错误框架。在你有很多函数要模拟的情况下,我之前发布的答案实在太麻烦了。原因是GMock使用对象接缝将生产代码替换为模拟代码。这依赖于C语言中不存在的多态类。

相反,要模拟C函数,您应该使用Link Seams,它在链接时用模拟代码替换生产代码。有几个框架可以做到这一点,但我最喜欢的是伪函数框架(FFF)。看看它,它比GMock简单得多。它在C++应用程序中也能很好地工作。

对于感兴趣的人,这里有一个由迈克尔羽毛关于不同类型的接缝的good article

票数 20
EN

Stack Overflow用户

发布于 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。

下面是我要测试的函数

代码语言:javascript
运行
复制
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进行单元测试

代码语言:javascript
运行
复制
// MOCKING C-Functions with GMOCK :)
#include <memory>
#include "gtest/gtest.h"
#include "gmock/gmock.h"
using namespace ::testing;
using ::testing::Return;

模拟BCM2835Lib函数

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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;
};

实例化模拟的库函数

代码语言:javascript
运行
复制
// instantiate mocked lib
std::unique_ptr<BCM2835Lib_MOCK> TestFixture::_bcm2835libMock;

将Mock与c-functions连接的伪库函数

代码语言:javascript
运行
复制
// 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的单元测试类

代码语言:javascript
运行
复制
// create unit testing class for BCM2835 from TestFixture
class BCM2835LibUnitTest : public TestFixture{
public:
    BCM2835LibUnitTest(){
        // here you can put some initializations
    }
};

使用googleTest和googleMock编写测试

代码语言:javascript
运行
复制
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);
}

结果:)

代码语言:javascript
运行
复制
[----------] 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)

希望它会有所帮助:) -对我来说,这是一个真正有效的解决方案。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31989040

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档