跳转至

C++单测Mock方式

1 GTest GMock

GMock可以满足如下测试需求:

  • mock一个类的虚函数和非虚函数

  • mock std::function

但是如果要测试非类成员函数和虚函数,即c-style函数。

Gmock是处理c++类的,如果要mock一个c-style函数,需要定义Interface的抽象类,然后通过mock类的方式去mock c-stryle函数。

如果要mock一个c语言函数,需要使用基于链接方式的,在测试的时候链接不同的cpp实现库。如果你的程序时c语言实现的,更好的是采用c mock的框架。比如https://github.com/meekrosoft/fff

参考:

2 c-style function mock

这里介绍两种mock方式,可以mock c-style function.

2.1 fff mock框架

使用fff mock框架,只需要引入fff.h头文件,

#include "fff.h"

#include <gtest/gtest.h>

DEFINE_FFF_GLOBALS;

// 函数原型

// xxxError xxxInit(const char *arg1);

// 通过mock宏FAKE_VALUE_FUNC,会生成一个xxxInit_fake对象,记录了参数值和返回值,可以更改函数返回值等

FAKE_VALUE_FUNC(xxxError, xxxInit, const char *);

class XClassTests : public testing::Test

{

public:

    // 参考Gtest框架,会在XClassTests test一开始调用SetUp函数

 void SetUp()

 {

  // Register resets

     RESET_FAKE(xxxInit);

  FFF_RESET_HISTORY();

  // non default init

  xxxInit_fake.return_val = 520;

 }

};

TEST(XClassTests, test_xxx_init_mock){

    int err = 0;

    aclInit_fake.return_val = 520;

    // call_xxxInit_func中会去调用xxxInit函数,这样会调用到mock的xxxInit函数

    err = call_xxxInit_func(0, "hello");

    ASSERT_EQ(xxxInit_fake.call_count, 1);

    RESET_FAKE(xxxInit);

}

更多例子可以参考:https://github.com/meekrosoft/fff/tree/master/examples

2.2 借助自定义的同名同参函数

// xxx_test.cpp

extern "C"{

    int xxxInit(const char* configPath){

        return 520;

    }

}

类似可以实现用自定义的malloc函数和free函数,wrap 系统的malloc和free函数,实现统计内存情况等功能。例如:

https://github.com/Toddz1/MemLeak

3 lmock

通过修改插入汇编代码,将mock函数地址设置到rax寄存器,然后jump到rax执行mock函数,可以mock 普通的函数和static函数,目前只实现了x86-64平台。

比如代码中的如下二进制,对应了jump rax。

"\xff\xe0"  =>  jmp rax

注: 可以通过gdb查看汇编和二进制以及源码

disassemble /r add(int)
/m 源码和汇编一起排列

/r 还可以看到16进制代码

3.1 C++ 工程实践(6):单元测试如何 mock 系统调用

https://www.cnblogs.com/Solstice/archive/2011/05/16/2047255.html

参考资料:

评论