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();
- }
- }