本文详细介绍了如何使用Mockcpp库进行接口、静态函数、成员函数的模拟测试,包括对纯虚函数、类中静态函数、已存在对象的虚函数以及嵌套调用对象成员函数的mock,并提供了多个测试用例。通过宏MOCKER_CPP的定义和MOCKER_METHOD的使用,实现了不同场景下的函数模拟,以验证代码行为。
摘要由CSDN通过智能技术生成
① 修改mockcpp的接口文件(追加一个宏),在mokc.h中追加MOCKER_CPP宏:
#define MOCKER_CPP(api, TT) MOCKCPP_NS::mockAPI(#api, reinterpret_cast<TT>(api))
② 使用例子:
#ifndef SAMPLE_H
#define SAMPLE_H
#include <gtest/gtest.h>
#include <mockcpp/mockcpp.hpp>
#include <memory>
using namespace std;
class ICalc
public:
virtual ~ICalc() {};
virtual int add(int a, int b) = 0;
virtual int add4(int a, int b) = 0;
class CalcImpl
: public ICalc
public:
virtual int add(int a, int b) {
return a + b;
virtual int add4(int a, int b) {
return a + b;
static int add2(int a, int b) {
return a + b;
int add3(int a, int b) {
return a + b;
class CalcImpl2
: public ICalc
public:
virtual int add(int a, int b) {
return a + b;
virtual int add4(int a, int b) {
return a + b;
static int add2(int a, int b) {
return a + b;
int add3(int a, int b) {
return a + b;
int add3(int a, int b, int c) {
return a + b + c;
class TestUse
public:
int add(int a, int b) {
calc.add3(a, b);
char* getData() {
char* sd = (char *)malloc(sizeof(char) * 100);
return sd;
CalcImpl calc;
CalcImpl calc2;
class CalcTest : public testing::Test
protected:
CalcTest() = default;
~CalcTest() = default;
virtual void SetUp() override
virtual void TearDown() override
// 测试纯虚类中的纯虚函数
TEST_F(CalcTest, test_xxx_001)
MockObject<ICalc> calc;
MOCK_METHOD(calc, add)
.stubs()
.will(returnValue(11));
EXPECT_EQ(11, calc->add(1, 1));
GlobalMockObject::verify();
// 测试纯虚类中的纯虚函数
TEST_F(CalcTest, test_xxx_002)
MockObject<CalcImpl> calc;
MOCK_METHOD(calc, add)
.stubs()
.will(returnValue(11));
EXPECT_EQ(11, calc->add(1, 1));
GlobalMockObject::verify();
// 测试类中的static函数
TEST_F(CalcTest, test_xxx_003)
MOCKER(&CalcImpl::add2)
.stubs()
.will(returnValue(11));
EXPECT_EQ(11, CalcImpl::add2(1, 1));
GlobalMockObject::verify();
// 测试已存在对象中的虚函数函数mock
TEST_F(CalcTest, test_xxx_004)
// add4和add为虚函数,第一个为this指针
CalcImpl impl;
MOCKER_CPP(&CalcImpl::add4, int (*)(CalcImpl*, int, int))
.stubs()
.will(returnValue(11));
MOCKER_CPP(&CalcImpl::add, int (*)(CalcImpl*, int, int))
.expects(once())
.with(any(), eq(1), eq(1))
.will(returnValue(222));
EXPECT_EQ(11, impl.add4(1, 1));
EXPECT_EQ(222, impl.add(1, 1));
GlobalMockObject::verify();
// 测试已存在对象中的成员函数mock
TEST_F(CalcTest, test_xxx_005)
CalcImpl impl;
MOCKER_CPP(&CalcImpl::add3, int (*)(CalcImpl*, int, int))
.expects(once())
.with(any(), eq(1), eq(1))
.will(returnValue(11));
EXPECT_EQ(11, impl.add3(1, 1));
GlobalMockObject::verify();
// 测试嵌套调用对象中的成员函数mock(开启mock)
TEST_F(CalcTest, test_xxx_006)
TestUse tu;
MOCKER_CPP(&CalcImpl::add3, int (*)(CalcImpl*, int, int))
.expects(once())
.with(eq(&tu.calc), eq(1), eq(1))
.will(returnValue(11));
EXPECT_EQ(11, tu.add(1, 1));
GlobalMockObject::verify();
// 测试嵌套调用对象中的成员函数mock(关闭mock)
TEST_F(CalcTest, test_xxx_007)
TestUse tu;
EXPECT_EQ(2, tu.add(1, 1));
GlobalMockObject::verify();
// 测试malloc的hook
//TEST_F(CalcTest, test_xxx_008)
// TestUse tu;
// MOCKER(malloc)
// .expects(once())
// .will(returnValue(NULL));
// GlobalMockObject::verify();
// 测试嵌套调用对象中的成员函数mock(关闭mock)
TEST_F(CalcTest, test_xxx_009)
TestUse tu;
EXPECT_EQ(2, tu.add(1, 1));
GlobalMockObject::verify();
// 测试只针对某个对象自己的虚函数mock
TEST_F(CalcTest, test_xxx_010)
CalcImpl tu;
CalcImpl2 tu2;
int (CalcImpl::*pfn)(int, int) = &CalcImpl::add4;
int (CalcImpl2::*pfn2)(int, int) = &CalcImpl2::add4;
MOCKER_CPP(tu.*pfn, int (*)(CalcImpl*, int, int))
.expects(once())
.with(any(), eq(1), eq(1))
.will(returnValue(11));
printf("1: %p\n", (void*)(tu.*pfn));
printf("2: %p\n", (void*)(tu2.*pfn2));
EXPECT_EQ(11, tu.add4(1, 1));
EXPECT_EQ(2, tu2.add4(1, 1));
GlobalMockObject::verify();
// 测试重载的情况
TEST_F(CalcTest, test_xxx_011)
CalcImpl2 tu2;
int (CalcImpl2::*pfn)(int, int, int) = &CalcImpl2::add3;
int (CalcImpl2::*pfn2)(int, int) = &CalcImpl2::add3;
MOCKER_CPP(tu2.*pfn, int (*)(CalcImpl2*, int, int, int))
.expects(once())
.with(any(), eq(1), eq(1), eq(1))
.will(returnValue(222));
MOCKER_CPP(tu2.*pfn2, int (*)(CalcImpl2*, int, int))
.expects(once())
.with(any(), eq(1), eq(1))
.will(returnValue(111));
EXPECT_EQ(222, tu2.add3(1, 1, 1));
EXPECT_EQ(111, tu2.add3(1, 1));
GlobalMockObject::verify();
#endif
可以使用gcc的链接选项 -Wl,–wrap=func。
会设置符号映射,在符号重定位阶段的时候,静态链接器对func函数的定位会定位到 __wrap_func 符号,对 __real_func 会定位到原func。
举例说明:
C Mock
libtest.h
/// @file libtest.h
#ifndef __LIBTEST_H__
#define __LIBTEST_H__
mock工具的作用是指定函数的行为(模拟函数的行为)。可以对入参进行校验,对出参进行设定,还可以指定函数的返回值。
几个相关概念
(1)mock规范:每个MOCKER(function)开始,跟一系列的.stubs、.with、.will等的内容的整体,称为一个mock规范。
(2)核心关键字:指stubs/defaults/expects/before/with/after/will/then/id等这些直接跟在点后面的关键字。
(3)扩展关键字:指onc
google mock是用来配合google test对C++项目做单元测试的。它依赖于googletest(参见我上篇文章《如何用googletest写单元测试》:http://blog.csdn.net/russell_tao/article/details/7333226),下面我来说说linux上怎么用它来做单元测试。
本文包括:1、如何获取、编译google mock;2、如何使用gm...
文章目录前言1. 下载网址2. 为什么选择Google Mock3. C++简单的例子3.1 使用流程4. 指定自己的期望
在进行单元测试时,我们想要测试自己缩写函数A,但是函数A却依赖于函数B,当函数B无法满足预期时就无法对函数A进行测试,主要由于下面几个原因:
函数B依赖于硬件设备
真实的函数B的返回值无法满足我们的预期
团队开发中函数B尚未实现
这时就需要对函数B进行打桩(仿真mock),使其达到我们预期的效果。
但是如同下面这种类型函数时,则需要深入下去,对基层的函数进行打桩:
编译出的libgtest.a后面用
注意:有可能编译会失败,是gtest需要C++11以上 可以在顶级的CMakeList.txt里加入 set(CMAKE_CXX_STANDARD 11)
二、mockcpp
下载地址:https://code.google.com/archive/p/mockcpp/downloads
TEST (HelloWorld, First) {
EXPECT_CALL (* MOCKER (func), MOCK_FUNCTION ()). Times ( Exactly ( 1 ))
. WillOnce ( Return ( " Hello world. " ));
EXPECT_EQ ( " Hello world. " , func ());
是我尝试解决此问题时的原型。
本文搭建单元测试环境用上的软件工具有:
1.1 gtest
gtest是一个跨平台的(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++单元测试框架,由google公司发布。gtest是为在不同平台上为编写C++测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。
1.2 mockcpp
Mockcpp是一个面向C/C++的mock框架。其指定(