Gmock如何mock系统函数

本文介绍了在C++开发中如何通过定义宏和gMock库实现对系统函数如open()的Mock,以便于单元测试中设置自定义返回值。作者提供了具体示例,展示了如何在源代码中添加改动、创建Mock函数和编写相应的测试代码以达到预期的测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景及其基本原理

在写UT代码过程中发现系统函数不太好打桩,网上也没搜到较好的方式。于是稍微研究了下。

在源代码中可以使用define宏来替换掉原本的系统函数,使用我们自己的mock函数,从而达到在单元测试中,随意设置自己的返回值。
下面举例将以系统函数open (const char *__path, int __oflag, ...)来进行测试
这是其中一种方法,有其他好的方法大家也可以交流

示例

需要测试的代码

//testfunc.cpp
#include<iostream>
#include<fcntl.h>
#include<unistd.h>

using namespace std;

void test_func()
{
    const char *filename="testFile";
    int fd = open(filename,O_WRONLY | O_CREAT);
    if (-1 == fd){
        cout<<"open failed"<<std::endl;
    }else if( -100 == fd ){
        cout<<"mock sucess"<<std::endl;
    }else{
        cout<<"open sucess"<<std::endl;
    }
    close(fd);
}

想要让程序输出mock sucess,就需要通过mock的方式设置返回值。

在源码中增加改动

//testfunc.cpp
#include<iostream>
#include<fcntl.h>
#include<unistd.h>

#ifdef UNIT_TEST
#include"openmock.hpp"
#define open openmock
#endif

using namespace std;

int test_func()
{
    const char *filename="testFile";
    int fd = open(filename,O_WRONLY | O_CREAT);
    if (-1 == fd){
        cout<<"open failed"<<std::endl;
    }else if( -100 == fd ){
        cout<<"mock sucess"<<std::endl;
    }else{
        cout<<"open sucess"<<std::endl;
    }
    close(fd);
    return fd;
}
#ifdef UNIT_TEST
#undef open openmock
#endif

通过宏的控制来打开或者关闭测试代码

创建mock函数的代码

//openmock.h
#pragma once

#include<gmock/gmock.h>

class MockOpen
{

public:
    MOCK_METHOD2(openmock,int(const char *__file, int __oflag));
};

extern MockOpen* g_MockOpen;

int openmock(const char *__file, int __oflag);
//openmock.cpp
#include"openmock.hpp"

int openmock(const char *file, int oflag)
{
    if (g_MockOpen == nullptr)
    {
        return -1;
    }
    return g_MockOpen->openmock(file,oflag);
}

编写ut代码

//unittest.cpp
#include<gtest/gtest.h>
#include"openmock.hpp"
#include"testopen.hpp"
MockOpen* g_MockOpen= nullptr;
using namespace ::testing;
class OpenTest : public testing::Test
{
public:
    void SetUp()
    {
        g_MockOpen = new MockOpen();
    }
    void TearDown()
    {
        delete g_MockOpen;
        g_MockOpen = nullptr;
    }
};

TEST_F(OpenTest,test)
{
    int val = -100;
    EXPECT_CALL(*g_MockOpen,openmock(_,_)).WillOnce(Return(val));
    auto ret = test_func();
    EXPECT_EQ(ret,val);

}

int main()
{
    testing::InitGoogleTest();
    return RUN_ALL_TESTS();
}

编译文件

g++ openmock.cpp unittest.cpp testopen.cpp -lgtest -lgmock -lpthread -DUNIT_TEST

结果输出

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from OpenTest
[ RUN      ] OpenTest.test
mock sucess
[       OK ] OpenTest.test (0 ms)
[----------] 1 test from OpenTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

这个时候就mock成功,并且设置到了我们自己期望的返回值。

Mock系统函数`open()`的方法与上面介绍的方法类似。这里以Linux系统为例,介绍如何使用gmock库来Mock`open()`函数。 1. 引入gmock库 在测试程序中引入gmock库的头文件: ``` #include <gmock/gmock.h> ``` 2. 定义Mock系统函数 在测试程序中定义一个Mock`open()`函数,例如: ``` // 假设要Mock的open()函数系统调用 int my_open(const char* pathname, int flags, ...) { return 123; // 这里返回一个固定的文件描述符 } ``` 3. 使用gmock库替换系统函数 在测试程序中使用gmock库的`TEST`宏定义一个测试用例,并在其中使用gmock库的`MockFunction`类来替换系统函数,例如: ``` TEST(MyTestSuite, MyTestCase) { // 使用MockFunction来替换open()函数 testing::MockFunction<int(const char*, int, ...)> mock_open; EXPECT_CALL(mock_open, Call("/path/to/file", O_RDONLY)).WillOnce(testing::Return(123)); // 调用需要测试的函数 // ... } ``` 在上面的代码中,`MockFunction`类用来创建一个Mock函数,`EXPECT_CALL`宏用来设置Mock函数的期望行为,这里我们期望Mock的`open()`函数被调用时返回一个固定的文件描述符。在测试用例中调用需要测试的函数时,Mock的`open()`函数会被自动调用并返回设置的文件描述符。 需要注意的是,Mock`open()`函数的实现要与系统调用的`open()`函数签名保持一致,即返回值为int类型,参数为const char*和int类型。在设置Mock函数的期望行为时,需要传入对应的参数值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值