背景及其基本原理
在写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成功,并且设置到了我们自己期望的返回值。