Gmock如何mock系统函数

背景及其基本原理

在写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成功,并且设置到了我们自己期望的返回值。

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在软件开发中,我们经常需要使用系统函数来完成一些操作,例如文件读写、网络通信等。但在某些情况下,我们需要在测试或调试时模拟系统函数的行为,以便更好地控制测试环境,这时就需要使用mock系统函数了。 Mock系统函数的一般步骤如下: 1. 定义一个和系统函数签名一致的mock函数,用于替换系统函数。 2. 在测试或调试时,将系统函数的调用替换为mock函数。 3. 在mock函数中模拟系统函数的行为,例如返回一个预设的值或抛出一个异常。 下面是一个C语言的例子,演示如何mock系统函数fopen(): ```c #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <stddef.h> #include <setjmp.h> #include <cmocka.h> /* 定义mock函数 */ FILE *mock_fopen(const char *filename, const char *mode) { check_expected_ptr(filename); check_expected_ptr(mode); return mock_ptr_type(FILE*); } /* 替换系统函数fopen() */ #define fopen mock_fopen /* 测试用例 */ static void test_fopen(void **state) { (void) state; /* unused */ /* 预设mock函数的返回值 */ expect_string(mock_fopen, filename, "/tmp/test.txt"); expect_string(mock_fopen, mode, "r"); will_return(mock_fopen, (FILE*)0x1234); /* 调用被测试函数 */ FILE *fp = fopen("/tmp/test.txt", "r"); /* 断言结果是否正确 */ assert_true(fp == (FILE*)0x1234); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_fopen), }; return cmocka_run_group_tests(tests, NULL, NULL); } ``` 在上面的例子中,我们使用了cmocka测试框架来mock系统函数fopen()。首先,我们定义了一个mock函数mock_fopen(),它和系统函数fopen()的签名一致。然后,我们使用宏#define将系统函数fopen()替换为mock函数mock_fopen()。接着,我们在测试用例test_fopen()中预设mock函数的返回值和参数,并调用fopen()函数。最后,我们使用断言来判断测试结果是否正确。 需要注意的是,使用mock系统函数时需要确保替换后的函数能够正确地模拟系统函数的行为,否则可能会导致测试结果不准确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值