C++类对象单元测试中的Mock使用

这篇具有很好参考价值的文章主要介绍了C++类对象单元测试中的Mock使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  在进行单元测试时,我们想要测试自己缩写函数A,但是函数A却依赖于函数B,当函数B无法满足预期时就无法对函数A进行测试,主要由于下面几个原因:

  • 函数B依赖于硬件设备
  • 真实的函数B的返回值无法满足我们的预期
  • 团队开发中函数B尚未实现

  这时就需要对函数B进行打桩(仿真mock),使其达到我们预期的效果。

但是如同下面这种类型函数时,则需要深入下去,对基层的函数进行打桩:

typedef struct
{
	int num;
	char *ptr;
	char bot[20];
} ST_OBJ;

int fun_A()
{
	fun_B();
	return 0;
}
void fun_B(ST_OBJ *ptObj)
{
	fun_C(ptObj);
	fun_D(ptObj);
	fun_E(ptObj);
}

1. 下载网址

https://github.com/google/googletest

2. 为什么选择Google Mock

  • 首先当然是我们遇到了在前言中所说的问题。
  • 其次Goole的Mock也是代码,也是工程师写的,自己当然也可以去实现,但费时费力,难以避免出错,对于初学者很难。
  • 再有就是Google Mock使用方便,只要#include"gtest / gtest.h"和"gmock / gmock.h",你已经准备好了。
  • 且功能强大。

3. C++简单的例子

  Mock的功能强大,所以也有很多细节,但这些在后面再去了解,首先看一下如何利用它去写一个TEST_F().
  我们的代码中有一个这样的类:

class Machine{ 
public:
	int IsSuccess(char *ptBotle);
	virtual bool Transform(Gadget* g) = 0; 
protected: 
   	virtual void Resume(); 
private: 
   	virtual int GetTimeOut(); 
}; 

  总之就是有很多函数,现在我们想要去对这个类的函数进行Mock

3.1 使用流程

  1. 声明一个Mock类继承自原始类
  2. public部分使用MOCK_METHOD声明Mock函数
class MockMachine : public Machine { 
public: 
/* MOCK_METHOD参数数量(函数名, 返回值类型(参数列表)) */
 	MOCK_METHOD1(IsSuccess, int(char *ptBotle));
    MOCK_METHOD1(Transform, bool(Gadget* g)); 
    MOCK_METHOD0(Resume, void()); 
    MOCK_METHOD0(GetTimeOut, int()); 

  到此就完成了,你并不需要去实现这些函数,函数的预期返回都可以在TEST_F中去指定,是我太小看Mock了,如果函数实现是固定的,那么在不同场景需要不同返回值时你还要去修改这个函数的实现吗?

  1. TEST_F中使用它
/* 步骤: */
	1. 导入GoogleMock中的一些命名空间, 方便后续指定自己Mock函数的期望
	2. 创建Mock对象
	3. 指定你对Mock函数的期望(一个函数应该被调用多少次,返回什么)
	4. 打桩完成了,开始业务代码的测试函数, 并对其进行断言(ASSERT)
#include "path/to/mock-turtle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast;                      // 1
using ::testing::Return;
 
TEST(test_machine, ResumeTheMachine)
{
  	MockMachine OBJ_mach;                      // 2
  	
  	EXPECT_CALL(OBJ_mach, Resume())            // 3
      	.Times(AtLeast(1));

  	ASSERT_TRUE(Fun_Resume(&OBJ_mach));        // 4
}

其中业务代码Fun_Resume的实现大概是这样:

bool Fun_Resume(Machine *Ship)
{
	/*
		...
	*/
	Ship->Resume();
	return TRUE;
}

5. 指定自己的期望

  如果定义的这个Mock供大家使用,那么每个人的需求都是不同的。即使一个人,在不同的单元测试用例中,对于该函数的期望也不可能不一样。

5.1 通用语法

使用EXPECT_CALL宏函数来定义.
  它有两个参数:创建的Mock对象、方法及其参数
  宏之后则是一些可选的配置

EXPECT_CALL(mock_object, method(matcher1, matcher2, ...))
    .With(multi_argument_matcher) //多个参数的匹配方式指定
    .Times(cardinality) //执行多少次
    .InSequence(sequences) //函数执行顺序
    .After(expectations) //指定某个方法只能在另一个方法后执行
    .WillOnce(action) //一般使用return,指定一次调用的输出
    .WillRepeatedly(action) //一直输出
    .RetiresOnSaturation(); //期待调用不会被相同的函数期待所覆盖

/*--------------------------*/
using ::testing::Return;

EXPECT_CALL(pencil, GetX(5))
    .Times(5)
    .WillOnce(Return(100))
    .WillOnce(Return(150))
    .WillRepeatedly(Return(200));
    /*
	pencil对象的GetX()方法将被调用五次,第一次返回`100`,第二次返回`150`,然后每次返回`200`.
	并且函数`GetX()`指定入参是5.
	*/

或者

TEST(mockcpp simple sample)
{
    MOCKER(function) / MOCK_METHOD(mocker, method)
        .stubs() / defaults() / expects(once())
        [.before("some-mocker-id")]
        [.with(eq(3))]
        [.after("some-mocker-id")]
        .will(returnValue(1)) / .will(repeat(1, 20))
        [.then(returnValue(2))]
        [.id("some-mocker-id")]
}

1、mock C函数用MOCKER;
mock 类成员方法先用MockObject mocker;声明一个mock对象,再用MOCK_METHOD(mocker, method)。

2、紧跟着MOCKER/MOCK_METHOD之后的是stubs、或者defaults、或者expects,三个必须有一个。(这是与AMOCK不同的地方,在这个层次上确定这三个关键字必须有一个,可以让mock语法更清晰)
stubs 表示指定函数的行为,不校验次数。
expects 与stubs的区别就是校验次数。(.expects(once()) / .expects(never()) / .expects(exactly(123)))
defaults 表示定义一个默认的mock规范,但它优先级很低;如果后面有stubs或者expects重新指定函数行为,就会按照新指定的来运行。

3、用will指定函数的返回值;
如果要指定20次调用都返回1,则用.will(repeat(1, 20));
要指定第一次返回1,第二次返回2,第三次返回3,就用
.will(returnValue(1))
.then(returnValue(2))
.then(returnValue(3))
如果你指定了前三次的返回值依次为1、2、3,那么第四次、第五次调用,都是返回最后的返回值3。

4、用id给一个mock规范指定一个名字,然后可以用after、before来指定多个mock应该的调用顺序。
注意before在with前,after在with后,id在整个mock规范的最后。

4.2 指定:调用次数

  当一个函数不会被调用时,则应将其指定为0,这样貌似Mock也有一点断言的意思.文章来源地址https://www.toymoban.com/news/detail-414512.html

using ::testing::_; 
EXPECT_CALL(foo, Bar(5)) 
    .Times(0);

4.3 指定:函数执行顺序

到了这里,关于C++类对象单元测试中的Mock使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mock单元测试----对于流程中的异常模拟,实现覆盖

    前言:进行单元测试时,有时候无法编写合适的测试用例来满足流程中的异常捕获和catch内的后续操作,此时mock模拟就有大作用了 例如:在进行删除操作时,为了防止在删除过程中突发数据库断连等情况,使用了try、catch进行异常的捕获和输出,但是在单元测试中编写测试实

    2024年02月12日
    浏览(32)
  • 掌握 xUnit 单元测试中的 Mock 与 Stub 实战

    上一章节介绍了 TDD 的三大法则,今天我们讲一下在单元测试中模拟对象的使用。 Fake - Fake 是一个通用术语,可用于描述 stub 或 mock 对象。 它是 stub 还是 mock 取决于使用它的上下文。 也就是说, Fake 可以是 stub 或 mock Mock - Mock 对象是系统中的 fake 对象,用于确定单元测试是

    2024年04月12日
    浏览(32)
  • C# 中的单元测试,如何使用单元测试进行程序测试和调试?

    单元测试是一种软件测试方法,用于测试单个功能或方法是否按预期工作。在 C# 中,可以使用 .NET 框架中的单元测试工具来编写和运行单元测试。 下面是使用 Visual Studio 内置的单元测试框架来创建一个简单的单元测试的步骤: 在 Visual Studio 中创建一个新的类库项目。 在新项

    2024年02月15日
    浏览(56)
  • Python中的单元测试框架:使用unittest进行有效测试

    在软件开发中,单元测试是一种测试方法,它用于检查单个软件组件(例如函数或方法)的正确性。Python 提供了一个内置的单元测试库,名为 unittest ,可以用来编写测试代码,然后运行测试,并报告测试结果。 本文将向你介绍如何使用 unittest 来编写和运行单元测试。通过阅

    2024年03月09日
    浏览(38)
  • SpringBoot 使用Mock单元测试

    测试一般分为两种黑盒测试和白盒测试。         黑盒测试又称为 功能测试 或 数据驱动测试 ,测试过程中,程序看作成一个黑色盒子,看不到盒子内部代码结构。         白盒测试又称为 结构测试 或 逻辑驱动测试 ,测试过程中,程序看作一个透明盒子,能够看清

    2024年03月20日
    浏览(40)
  • [C++] 基础教程 - 如何使用google test进行单元测试

    https://download.csdn.net/download/u011775793/88601877 单元测试是一种软件测试方法,用于测试代码中的最小可测试单元。在软件开发中,我们通常将代码分解为多个模块或类,每个模块或类都有自己的功能和行为。单元测试的目的是确保每个模块或类都能正常工作,不会影响其他模块或

    2024年02月04日
    浏览(38)
  • 测试人必会的Python内置库:unittest.mock(单元测试mock的基础使用)

    unittest.mock是用于在单元测试中模拟和替换指定的对象及行为,以便测试用例更加准确地进行测试运行。例如对于以下代码,想要针对函数func_a写一个简单的单元测试: 但是这样的话,函数func_b和func_c的逻辑都需要一起测试,在单元测试中这明显是不合理的,对于想要测试的

    2024年02月01日
    浏览(40)
  • Java中的JUnit是什么?如何使用JUnit进行单元测试

    JUnit是Java中最流行的单元测试框架之一。它可以帮助开发人员在代码编写过程中检测出错误和异常,从而提高代码的质量和可靠性。 JUnit是一个由Kent Beck和Erich Gamma创建的开源Java单元测试框架,它已经成为Java开发中最常用的测试框架之一。这个框架的主要目的是为了简化单元

    2024年02月12日
    浏览(58)
  • [Springboot 单元测试笔记] - Mock 和 spy的使用

    通常单元测试中,我们会隔离依赖对于测试类的影响,也就是假设所有依赖的一定会输出理想结果,在测试中可以通过Mock方法来确保输出结果,这也就引入另一个测试框架Mockito。 Mockito框架的作用就是模拟接口功能,并不运行模拟接口的实际逻辑,而是直接输出一个假定结果

    2024年02月13日
    浏览(33)
  • python技术栈 之 单元测试中mock的使用

    一、什么是mock? mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。 二、mock的作用 特别是开发过程中上下游未完成的工序导致当前无法测试,需要虚拟某些特定对象以便测试。 unittest是python内置的单元测

    2024年02月13日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包