接口(宏)简单介绍
SMOCK
StubMock类的单例对象V_ADDR
获取类虚拟函数地址O_ADDR
获取重载函数地址(只支持类成员函数)NF_SMOCK
函数打桩F_SMOCK
函数打桩,会去调用NF_SMOCK
,调用时默认第一个参数为0SMOCK_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函数,一般分为两种:
- Return(), 不加返回值用于匹配返回类型为void的打桩函数
- Return(x), 用于匹配返回类型与x类型相同的打桩函数