PHPUnit学习05---Mock使用进阶
本文目的
最近使用php开发项目,并用phpunit进行单元测试,使用phpunit的mock机制有一段时间了,决定记录使用经验,方便以后查阅。
mock例子
public function testBit(){ $oClientMock = $this->getMock('SomeClient'); // 创建mock对象 $oClientMock->expects($this->once()) // 设定次数 ->method('ExecuteCommand') // 设定方法 ->with(CPU_BIT_CMD) // 设定方法入参 ->will($this->returnValue('some')); // 设定方法返回值 $oHardware = new MHardware($oClientMock); $this->assertEquals('32', $oHardware->CpuBit()); // 调用方法并断言 }
简而言之,使用mock一般有下面几步:
- getMock 创建mock对象(必须有)
- method 设置期望调用的方法(必须有)
- expects 设置方法调用的次数(必须有)
- with 设置调用方法时的入参(可选)
- will 设置调用方法后的返回值(可选)
getMock函数签名详解
getMock有7个参数,一般只需要使用第一个参数指定被mock的类即可,但是如果需要更灵活的配置mock,有必要了解其他参数:
- String – Required – 需要mock的类的名称
- Array – Optional – 需要mock的函数名称数组,默认情况下,会mock所有函数(即给所有函数一个空的实现),但是如果设置了需要mock的函数,那么其他函数将不会被mock,按照原来的方式执行。
- Array – Optional – 需要传入给构造函数的参数,getMock方法帮你调用了构造函数,所以这里通过一个数组,给你设置构造函数参数的机会
- String – Optional – 给这个mock类起一个名称,这样可以使用这个新名称创建许多同样的mock类实例。
- Boolean – Optional – true将调用原始对象的构造函数,false将不掉用,默认为true
- Boolean – Optional – true将可以调用原始类的clone函数,false则无法调用。
- Boolean – Optional – false将禁止__autoload函数被调用,当mock对象被创建时。
匹配器(Matchers)
匹配器相当于调用mock方法的量词,作为expects函数的参数传给mock对象,用于设定期望的调用次数,主要有下面几个:
once() 期望方法只调用一次,否则测试失败
never() 期望方法从不被调用,否则测试失败
any() 期望调用任意次,测试永远不会因此失败。
at($index) 期望方法被第$indexd调用的行为,$index从0开始,一般会配合with或will使用。值得注意的是$index是针对特定mock对象而言的,而不是针对特定mock对象的特定方法。也就是说,mock对象A任意一个方法被调用一次,$index会增加1。
exactly($times) 期望执行准确的次数,否则测试失败
atLeastOnce() 期望执行至少一次,否则测试失败
约束(Constraints)
约束和with一起使用,用于设定mock函数的输入,约束有很多,主要分为一下几大类
[数组]
arrayHasKey(mixed $key) 断言入参数组是否有指定的键
contains(mixed $value) 断言入参数组是否有指定的值
[逻辑]
logicalAnd($constraint,$constraint) 断言两个参数逻辑和
logicalNot($constraint) 断言参数逻辑否
logicalOr($constraint,$constraint) 断言两个参数逻辑或
logicalXor($constraint,$constraint) 断言两个逻辑异或
[字符串]
matchesRegularExpression($pattern) 断言入参是否匹配正则表达式
stringContains($string, $case) 断言入参是否包含表达式
stringEndsWith( $suffix) 断言入参是否有此后缀
stringStartsWith(string $prefix) 断言入参是否有次前缀
[比较]
identicalTo($value) 断言入参===当前值
equalTo($value, $delta = 0, $maxDepth = 10) 断言入菜是否==当前值
lessThan($value) 断言入参<当前值
lessThanOrEqual(mixed $value) 断言入参<=当前值
greaterThan(mixed $value) 断言入参>当前值
greaterThanOrEqual(mixed $value) 断言入参>=当前值
[类和对象]
attribute($constraint, $attributeName) 将约束赋给指定属性或对象
attributeEqualTo($attributeName, $value, $delta = 0, $maxDepth = 10) 断言value是否与当前对象的某个属性相等
classHasAttribute($attributeName) 断言当前类是否具有摸个属性
classHasStaticAttribute($attributeName) 断言当前类是否具有某个静态属性
hasAttribute($attributeName) 断言当前对象是否有指定的属性
[基本类型]
isFalse() 断言当前值为FALSE
isTrue() 断言当前对象是否为TRUE
isInstanceOf(string $className) 断言当对象是某个类的实例
isNull() 断言当前对象是否为NULL
isType($type) 断言当前对象是某个具体的类型
[其他]
anything() 接受任何入参
fileExists() 断言当前入参代表的文件是否存在
返回
设定返回值,与will一起使用,用于设定mock函数的返回值,主要方法方法如下:
returnValue($value) 返回字面意思
throwException($exception) 此方法在调用时抛出指定异常
returnArgument($index) 返回第$index个参数,从0开始
returnCallback($fun) 返回值通过回调函数生成,函数签名与被mock的函数相同
onConsecutiveCalls(arg0,arg1,…) 设定返回值列表,这样可以控制被返回值的顺序,更灵活的控制返回值,最好与匹配器any或atLeastOnce结合使用。
参考文档