美文网首页
使用googlemock来模拟全局函数的实现

使用googlemock来模拟全局函数的实现

作者: 小矮人Keep | 来源:发表于2020-02-14 15:44 被阅读0次

在使用googlemock时,在有些函数调用中,可能涉及到未开发完成的函数。
这个时候就需要对该未完成的函数(或者涉及网络、数据库的操作函数)进行mock。
解决方案出处

下面的代码中account_update函数使用了db_update这个函数,它会直接调用数据库,是个重量级的依赖。 为了对这段代码进行测试, 需要把db_update函数隔离,怎么处理?

#include <DFHLItem.h>
#include <DHLSRecord.h>
extern int db_update(int, struct DFHLItem *);

void account_update(
    int account_no, struct DHLSRecord *record, int activated)
{
    if (activated) {
        if (record->dateStamped && record->quantity > MAX_ITEMS) {
            db_update(account_no, record->item);
        } else {
            db_update(account_no, record->backup_item);
        }
    }
    db_update(MASTER_ACCOUNT, record->item);
}

方法一:利用C语言的预处理(在编译之前进行Mock)
先引入一个头文件:

#include <DFHLItem.h>
#include <DHLSRecord.h>

extern int db_update(int, struct DFHLItem *);

#include "localdefs.h"

void account_update(
    int account_no, struct DHLSRecord *record, int activated)
{
    if (activated) {
        if (record->dateStamped && record->quantity > MAX_ITEMS) {
            db_update(account_no, record->item);
        } else {
            db_update(account_no, record->backup_item);
        }
    }
    db_update(MASTER_ACCOUNT, record->item);
}

在该头文件中提供一个db_update的定义,注意,使用了#define把db_update展开为一段代码

#ifdef TESTING
...
struct DFHLItem *last_item = NULL;
int last_account_no = -1;
#define db_update(account_no,item)\
    {last_item = (item); last_account_no = (account_no);}
...
#endif

这样C语言编译器可以把所有的db_update都替换成{last_item = (item); last_account_no = (account_no);}, 这段代码会记录下最后的item和account_no,可以供测试中的验证使用
使用宏就会丢失类型安全,如果逻辑复杂的话,很容易出错谨慎使用该方法。

方法二: 使用函数指针(编译期进行mock)
(1)首先写一个函数指针: int (*db_update)(int, struct DFHLItem *)
(2)把原来的db_update 改名为 int db_update_production(int, struct DFHLITem *)
(3) 编写一个mock实现 int db_update_mock(int, struct DFHLITem *)
(4) 最后使用条件编译来制定到底用哪个函数

#ifdef TESTING
   db_update = db_update_mock
#else
   db_update = db_update_production
#endif

该方法很灵活, 可以随意通过函数指针进行替换,还能兼顾类型安全 ,推荐使用。

方法三: 在编译之后 Link时候进行替换
这就需要编写包括db_update的库函数,在link的时候使用这个假的库函数。 当然Link出来的exe文件指示一个测试版本。
如果需要函数很多, 还有db_insert, db_delete等等, 这些函数都需要在假的库函数中进行实现, 开销不小。

看过《修改代码的艺术》这本书的人可能对上面的例子有些眼熟,不错,上面的方法和例子就是从这本书中来的。这本书对于处理遗留代码提供了大量的方法,强烈推荐阅读!

相关文章

  • 使用googlemock来模拟全局函数的实现

    在使用googlemock时,在有些函数调用中,可能涉及到未开发完成的函数。这个时候就需要对该未完成的函数(或者涉...

  • 模块化的演变

    全局函数的方式 在html中要实现加减的运算 在header中实现加减function,将重复使用的代码封装到函数...

  • 线程特有数据(Thread Specific Data)

    在单线程程序中,我们经常要使用全局变量来实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量...

  • Go学习日志:基本概念及通道

    变量声明 简短声明方法,使用:=,在函数内部使用,外部无法通过。 全局变量 使用var来定义。 函数调用 func...

  • JS中的闭包

    逃脱(内部函数脱离定义它们的外部函数) 全局变量 返回值 实现一个变量的累加 全局变量 使用闭包 闭包中的this...

  • Jest - 模拟函数 mock function

    模拟函数通过擦去真正的函数实现,捕获函数调用(调用传参),当使用 new 实例化的时候捕获构造函数,并允许测试时配...

  • ES6的class概念(2018-06-20)

    一直以来,开发者都是使用函数function和原型prototype来模拟类class实现面向对象的编程。ES6给...

  • 剑指offer 矩阵中的路径

    思想:标准的回溯法实现: 使用hash表标记元素是否已经被访问 使用全局变量以及在函数内定义函数尽量减少代码量

  • js对象创建及链式调用

    一、使用对象的原因 不会污染全局环境,和别人协同合作时,不会互相影响。所以,尽量使用对象来收编变量。 函数也是全局...

  • Android kotlin静态属性、静态方法

    Kotlin类不支持静态方法和成员,但Kotlin支持全局函数和变量,因此我们可以直接使用全局函数和变量来代替类中...

网友评论

      本文标题:使用googlemock来模拟全局函数的实现

      本文链接:https://www.haomeiwen.com/subject/hktjfhtx.html