1、mock C函数或者类的静态成员方法用MOCKER;
mock 类的非静态成员方法需要先用MockObject<MyClass> mocker;
声明一个mock对象,再用MOCK_METHOD(mocker, method)来mock指定方法。
2、紧跟着MOCKER/MOCK_METHOD之后的是stubs、或者defaults、或者expects,三个必须有一个。(这是与AMOCK不同的地方,在这个层次上确定这三个关键字必须有一个,可以让mock语法更清晰)
stubs 表示指定函数的行为,不校验次数。
expects 与stubs的区别就是校验次数。(.expects(once()) / .expects(never()) / .expects(exactly(123)))
defaults 表示定义一个默认的mock规范,但它优先级很低;如果后面有stubs或者expects重新指定函数行为,就会按照新指定的来运行。(一般用在setup中)
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规范的最后。
5、使用mockcpp时,校验是否按照mock规范进行调用的,应该用:
GlobalMockObject::verify();
verify之后,会自动执行reset。(如果是对象的mock,应该用mocker.verify(),同样也会自动reset。)
如果单单只想reset,也可以:(这很少见,难道前面你定义的mock规范都不想要了,也不校验?那为何要定义呢?)
GlobalMockObject::reset();
一般是在teardown中调用verify。
6、如果要对某个函数(比如add)指定多个调用不同的行为(多个mock规范),比如调用入参为1,2时,返回30;调用入参为3、4时,返回700。那么可以这样写:
MOCKER(add)
.stubs()
.with(eq(1), eq(2))
.will(returnValue(30));
MOCKER(add)
.stubs()
.with(eq(3), eq(4))
.will(returnValue(700));
7、如果对于6的例子,还希望校验次数,则把stubs改为expects(once())这样的即可。
8、如果对于6的例子,还希望对调用顺序做严格要求,必须第一次调用参数是1、2,第二次是3、4,那么可以这样写:
MOCKER(add)
.stubs()
.with(eq(1), eq(2))
.will(returnValue(30))
.id("first");
MOCKER(add)
.stubs()
.with(eq(3), eq(4))
.after("first")
.will(returnValue(700));
9、指定出参的方法(例子中出参为指针类型,出参为引用的outBound(var)即可,更加简单)
void function(int *val)
应该用下面方式来指定出参:
int expect = 10;
MOCKER(function)
.stubs()
.with(outBoundP(&expect, sizeof(expect)));
10、对同一个函数指定多个mock规范,那么这些mock规范一般是应该在输入方面有差异的,否则没必要指定多个。而且,在输入方面无差异的两个mock规范,让mockcpp内部无法判断是否满足规范约束。
比如,测试函数 void function(int in, int &out),前面一个是入参,后面一个是出参,希望in为1时,输出out为100,in为2时,输出out为3,那么应该这样写:
int out = 100;MOCKER(function) .expects(once()) .with(eq(1), outBound(out));out = 3;MOCKER(function) .expects(once()) .with(eq(2), outBound(out));
假设你把eq(1)、eq(2)写为any(),那么mockcpp会判断你的两个调用function(1, out)和function(2, out)都符合第一个mock规范,从而报告与你定义的次数1不匹配。
11、有时候需要对同一个函数指定多个mock规范,并且它们是有规律的,那么可以借助循环来简化代码。
假设要mock的函数是void function(int in),希望它依次以0、1、2…10为入参被调用,每次都调用一次,那么可以像这样写:
MOCKER(function) .expects(once()) .with(eq(0)) .id("0");for (int i = 1; i <= 10; i++){ MOCKER(function) .expects(once()) .with(eq(i)) .after(string(i - 1)) .id(string(i)); }
12、spy约束关键字应用举例。
spy的作用是监视,下面例子,就是监视test在调用func时,传入的值是多少。有些时候,测试用例需要这样的值,这种方式是很有效的。
void func(int var){}void test(){ int var = 10; func(var);}TEST(sample test){ int var; MOCKER(func) .stubs() .with(spy(var)); .with(eq(10)); test(); ASSERT_EQ(var, 10); }
13、check约束关键字的用法。
约束关键字中,有很多都是对入参进行检查的,比如eq、neq、lt、gt等等,但它们都只实现了非常简单的检查。
如果用户想做一个定制化的检查,那么就可以用check。
例1:假设用户想检查入参p指向的结构的字段b是不是10,那么可以如下这样写:
struct AA { int a; int b;};void func(int in, AA *p){}// 实现一个检查函数,入参类型跟要检查的入参相同,返回值为bool,返回true表示检查通过。bool check_func(AA *p){ if ( p->b == 10) { return true; } return false;}TEST(sample test){ MOCKER(func) .stubs() .with(any(), checkWith(check_func)); func(in, p);}
例2:如果需要检查b是否小于某个给定的数,而且有多个用例,每个用例中与b比较的数不同,则可以使用仿函数的方式。
// 实现一个仿函数类,即重载“()”运算符的类。struct CheckFunctor { CheckFunctor(int _base) : base(_base){} bool operator ()(AA *p) { if (p->b < base) return true; return false; } int base;};TEST(b should less than 100){ MOCKER(func) .stubs() .with(any(), checkWith(CheckFunctor(100))); func(in, p);}TEST(b should less than 200){ MOCKER(func) .stubs() .with(any(), checkWith(CheckFunctor(200))); func(in, p);}
14、只要打桩了,那么就不会运行原函数,都是与mock规范匹配,运行桩。
下面例子中,对add的入参为1、2的情况打桩了,如果调用了入参为2、3的情况,则会报告调用在允许的mock规范列表中不存在的错误。
TEST(sample test){ MOCKER(add) .expects(once()) .with(eq(1), eq(2)) .will(returnValue(100)); ASSERT_EQ(100, add(1, 2)); ASSERT_EQ(50, add(2, 3));}
15、带有返回值的函数,MOCKER后面必须有will,否则mockcpp认为无返回值,校验时会发现返回类型不匹配。
1. 背景
mock++是一个C/C++语言的mock框架。它最初出现的原因并不是为了重新发明轮子,也不是为了做Yet Another C++ mock framework。
在mock++出现之前,在互联网上可以找到的C++ Mock框架只有mockpp; 在我们最初的敏捷开发实践中,它也就是我们唯一的选择。虽然mockpp 是一个优秀的框架,但它的实现使用了非常复杂的模版技术,这带来了漫长的编译时间,和非常晦涩难懂的编译错误信息。这对于TDD的步伐有着非常负面的影响。另外,mockpp所提供的功能在某些
MOCKER(function) / MOCK_METHOD(mocker, method)
.stubs() / defaults() / expects(never() | once() | exactly(3) | atLeast(3) | atMost(3) )
[.before("some-mocker-id")]
[.with( any() | eq(3) | neq
#include "mockcpp/mockcpp.hpp"
2.mockcpp在2.4版本后没有了check关键字,代之以checkWith (注意大小写,因为还有一个CheckWith,坑爹)
3.如何检查private的成员
尽量少的使用模版技术,以提高编译性能,降低错误信息的晦涩性;
框架产生的错误信息格式应该简单直观,信息应该全面,以帮助程序员更加快速的了解和定位问题;
生成一个mock对象应该尽可能的简单;
框架应该具备良好的扩展性,以应对各种特殊的需要;
能够支持针对静态函数的mock。
Mockcpp相关概念
mock规范
每个MOCKE
Mocker 使用教程
mockerA Docker-type runtime, written in 100% Python项目地址:https://gitcode.com/gh_mirrors/moc/mocker
Mocker 是一个基于 Swift 编写的库,它通过实现自定义 URLProtocol 来使数据请求模拟成为可能。这个项目简化了在不需要修改实际代码的情况下,对网络...
Mocker
Mock Alamofire and URLSession requests without touching your code implementation
项目地址: https://gitcode.com/gh_mir...
freemark生成mocker.js
let Mock=require('mockjs');//引入mockjs模块
let Random = Mock.Random;
module.exports = function() {
var data = {//定义等下要返回的json数据
news: []
data.news.pus