gtest Unitest 打桩优化

接口(宏)简单介绍

  • SMOCK StubMock类的单例对象

  • V_ADDR 获取类虚拟函数地址

  • O_ADDR 获取重载函数地址(只支持类成员函数)

  • NF_SMOCK 函数打桩

  • F_SMOCK 函数打桩,会去调用NF_SMOCK,调用时默认第一个参数为0

  • SMOCK_CLEAR 清除所有打桩函数

整体的简单介绍

  • StubMock是继承Stub的一个单例类,SMOCK宏是获取单例对象的简便方式,因为是继承Stub并且一些功能限制,因此需要修改Stub源代码:

    • private 修改成protected

    • 将虚构函数中的清除打桩函数操作单独变成一个函数,SMOCK_CLEAR宏将会调用该函数。

  • 因为使用仍然是Stub的打桩,因此整体需要的两个东西不会改变,即被打桩函数的地址和打桩函数的地址,StubMock优化了打桩函数的地址,它提供了更友好的交互方式:

    • lambda表达式

    • gmock的action类

  • 关于为什么使用NF_SMOCK为什么第一次参数需要带一个编号,因为实现问题(不想使用__COUNTER__宏),对于每一种函数类型同一时刻只能有一个被打桩,因此需要添加不同的编号来做到打桩一定成功。

推荐每一个打桩都用不同的编号,否则会给自己精神压力,因为会需要一直查看是否有相同类型的函数被打桩。

使用方式

静态函数打桩

// unistd.h
extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur;
// string.h
extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));

using namespace testing;

class CLS {
public:
  static void s1() {}
};

TEST {
  // use lambda
  NF_SMOCK(0, read, [] { return 0; }); // have return type
  NF_SMOCK(1, read, [] {}); // no return type
  NF_SMOCK(2, ADDR(CLS, s1), [] {})); // class static function
  
  // use gmock action
  NF_SMOCK(0, read, Return(0)); // have return type
  NF_SMOCK(1, read, Return()); // no return type
  NF_SMOCK(2, ADDR(CLS, s1), Return()); // class static function
  
  // do something
  
  SMOCK_CLEAR; // clear
}

类成员函数打桩

using namespace testing;

class CLS {
  int cfn(int x) const { return 0; }
}

TEST {
  // use lambda
  NF_SMOCK(0, ADDR(CLS, cfn), [] { return 1; }));
  
  // use gmock action
  NF_SMOCK(0, ADDR(CLS, cfn), Return(1));
  
  // do something
  
  SMOCK_CLEAR; // clear
}

虚函数打桩

using namespace testing;

class CLS {
  virtual int vir_fun() const { return 0;}
}

TEST {
  // use lambda
  NF_SMOCK(0, V_ADDR(CLS, cfn), [] { return 1; }));
  
  // use gmock action
  NF_SMOCK(0, V_ADDR(CLS, cfn), Return(1));
  
  // do something
  
  SMOCK_CLEAR; // clear
}

重载函数打桩

O_ADDR(arg1, arg2, arg3, arg4, arg5)

  • arg1 类名

  • arg2 函数名

  • arg3 返回类型

  • arg4 参数列表

  • arg5 类函数描述符列表(const, …)

class CLS {
  int fun() const { return 0;}
  int fun(double) const { return 0;}
};

TEST(a, b) {
  // use lambda
  NF_SMOCK(0, O_ADDR(CLS, fun, int, (), (const)), [] { return 1; });
  NF_SMOCK(1, O_ADDR(CLS, fun, int, (double), (const)), [] { return 2; });
  
  // use gmock action
  NF_SMOCK(0, O_ADDR(CLS, fun, int, (), (const)), Return(1));
  NF_SMOCK(1, O_ADDR(CLS, fun, int, (double), (const)), Return(2));
  
  // do something
  
  SMOCK_CLEAR; // clear
}

lambda表达式使用的场景

lambda一般用于逻辑不单一的场景,如:

// unistd.h
extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur;

TEST {
  NF_SMOCK(0, read, []{
    static int cnt = 0;
    cnt++;
    if (cnt == 1) return 0;
    return -1;
  });
  
  // do something
  
  SMOCK_CLEAR; // clear
}

gmock action

gmock action中最常用是就是Return函数,一般分为两种:

  1. Return(), 不加返回值用于匹配返回类型为void的打桩函数

  2. Return(x), 用于匹配返回类型与x类型相同的打桩函数

代码

橘色的喵/custom_gtest_stub

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘色的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值