2015
Feb
05
當一個 PHP 程式有 require 到多個 library 時,Unit test 會變得很難完成,或者是根本無法測試,而 Mock Object 就是一個用來處理這種很難測試的 PHP 程式。
下列這個網址是 phpunit 官方文件。
PHP Mock Object 可以覆寫 class 中Method 的實作方式,直接定義 return 結果,不但如些,它還能定義第一次呼叫,與第二次,第 N 次呼叫的 return 結果,讓每一次都有不同的 return 值,對於那種常常會被 Call 超過一次的 Method 來說,不用 Mock Object 的話,工程師就得寫很多 Test 程式來偽造 Method。
使用 Mock Object 時,要注意 Private 與 Protected 屬性的 Method 與 Property 都是不能夠被 Mock 掉的,如果你的程式用到很多 Private 或是 Protected ,就一樣很容易寫 Unit Test 時會卡住...
Method 不能是 Private 或是 Protected 。
Property 不能是 Private 或是 Protected 。
Mock Object 範例
我先定義了一個簡單的 class ,裡面有兩個 Method 分別是 calculate 與 getPrice,而 getPrice 又會去 call calaulate ,當我要測試 getPrice 時,就會被迫連 calaulate 這個 Method 也一起測試,這時我就可以用 Mock Object 來定義 calculate 的 return 值,單純的測試 getPrice。
php source code
- //
- class MyClass {
- public function calaulate() {
- ...
- }
- public function getPrice() {
- $priceInfo = $this->calaulate();
- $totalPrice = $priceInfo['sumPrice'] + $priceInfo['fee'];
- return $totalPrice;
- }
- }
Tester for using Mock Builder
- //
- class testMyClass extends PHPUnit_Framework_TestCase {
- public function test_getPrice() {
- $tester = $this->getMockBuilder('MyClass')
- ->setMethods(array("calculate"))
- ->getMock();
- $tester->expects($this->any())
- ->method('calculate')
- ->will($this->returnValue(array("sumPrice" => 979, "fee" => 21)))
- $totalPrice = $tester->getPrice();
- $this->assertEquals(1000, $totalPrice);
- }
- }
Mock constructor
constructor
- //
- class testMyClass extends PHPUnit_Framework_TestCase {
- public function test_getPrice() {
- $tester = $this->getMockBuilder('MyClass')
- ->setConstructorArgs(array("p1", "p2"));
- ->setMethods(array("calculate"))
- ->getMock();
- }
- }