[英]Mocking/Stubbing an Object of a class that implements arrayaccess in PHPUnit
這是我正在為其編寫測試套件的類的構造函數(它擴展了 mysqli):
function __construct(Config $c)
{
// store config file
$this->config = $c;
// do mysqli constructor
parent::__construct(
$this->config['db_host'],
$this->config['db_user'],
$this->config['db_pass'],
$this->config['db_dbname']
);
}
傳遞給構造函數的Config
類實現了 php 內置的arrayaccess
接口:
class Config implements arrayaccess{...}
如何模擬/存根Config
對象? 我應該使用哪個,為什么?
提前致謝!
如果您可以輕松地從數組創建Config
實例,那將是我的偏好。 雖然您希望在可行的情況下單獨測試您的單元,但簡單的合作者(例如Config
應該足夠安全以用於測試。 設置它的代碼可能比等效的模擬對象更易於閱讀和編寫(不易出錯)。
$configValues = array(
'db_host' => '...',
'db_user' => '...',
'db_pass' => '...',
'db_dbname' => '...',
);
$config = new Config($configValues);
話雖如此,您可以像模擬任何其他對象一樣模擬實現ArrayAccess
對象。
$config = $this->getMock('Config', array('offsetGet'));
$config->expects($this->any())
->method('offsetGet')
->will($this->returnCallback(
function ($key) use ($configValues) {
return $configValues[$key];
}
);
您還可以使用at
強加特定的訪問順序,但這樣會使測試變得非常脆弱。
提出問題后 8 年,首次回答后 5 年,我遇到了同樣的問題並得出了類似的結論。 這就是我所做的,這與 David 接受的答案的第二部分基本相同,除了我使用的是更高版本的 PHPUnit。
基本上你可以模擬ArrayAccess
接口方法。 只需要記住,您可能想要模擬offsetGet
和offsetExists
(您應該始終在使用之前檢查數組鍵是否存在,否則您可能會在代碼中遇到E_NOTICE
錯誤和不可預測的行為,如果它不存在)。
$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);
$thingyWithArrayAccess->method('offsetGet')
->with('your-offset-here')
->willReturn('test-value-1');
$thingyWithArrayAccess->method('offsetExists')
->with($'your-offset-here')
->willReturn(true);
當然,您可以在測試中使用真正的數組,例如
$theArray = [
'your-offset-here-1' => 'your-mock-value-for-offset-1',
];
$thingyWithArrayAccess = $this->createMock(ThingyWithArrayAccess::class);
$thingyWithArrayAccess->method('offsetGet')
->willReturnCallback(
function ($offset) use ($theArray) {
return $theArray[$offset];
}
);
$thingyWithArrayAccess->method('offsetExists')
->willReturnCallback(
function ($offset) use ($theArray) {
return array_key_exists($offset, $theArray);
}
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.