一 Mock簡介
當我們對A類進行單元測試時,A類可能依賴了B類,為了減少依賴,方便A類方法的測試,我們可以模擬一個B類,簡單規定其各方法的返回值(而非真正實現具體邏輯)。
Phpunit中提供了一套模擬類的api,簡單使用如下:
class StubTest extends PHPUnit_Framework_TestCase
{
public function testStub()
{
// Create a stub for the SomeClass class.
$stub = $this->getMock(‘SomeClass’);
// Configure the stub.
$stub->expects($this->any())
->method(‘doSomething’)
->will($this->returnValue(‘foo’));
// Calling $stub->doSomething() will now return ‘foo’.
$this->assertEquals(‘foo’, $stub->doSomething());
}
}
在這個例子中,我們得到了一個’SomeClass’的模擬,規定其可以被調用任意次,如果調用doSomething方法,將得到值foo。
二 問題
我們知道,對於一個單例類,其constructor方法為private,而getMock的實現,默認是要調用原類的constructor方法。
如果SomeClass為單例,phpunit將會提示
Call to private SomeClass::__construct() from context ‘PHPUnit_Framework_TestCase’
這時,我們的測試該如何進行呢?
三 解決
仍然使用getMock進行模擬。
只要將其第5個參數設為false即可。其含意是:不調用原對象的構造函數。
$stub = $this->getMock(‘SomeClass’, array(), array(), ”, false);
不得不說,這樣使用有點復雜。
如果你使用的是phpunit3.5及以上版本, 那麼有更易用的api。你可以這樣禁掉對原有constructor方法的調用:
$stub=$this->getMockBuilder(‘SomeClass’)->disableOriginalConstructor()->getMock();
附:
對getMock的6個可選參數的詳解,參見:http://www.phpunit.de/manual/3.6/en/test-doubles.html
手冊中並未提及它們的默認值,經測試得到結果如下,貼出來方便大家使用。
array(), array(), ”, false, false, false
即
$stub=$this->getMockBuilder(‘SomeClass’)
等同於:
$stub=$this->getMockBuilder(‘SomeClass’,array(), array(), ”, true, false, false)