本文目的
最近使用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結合使用。
參考文檔