5
使用PHPUnit和模擬對象,我試圖測試一些使用get_class
來確定對象是否被過濾器包含的代碼。使用PHPUnit模擬對象使用get_class的測試代碼
下面是類待測試:
class BlockFilter implements FilterInterface
{
private $classes;
public function __construct(array $classes = array())
{
$this->classes = $classes;
}
public function isIncluded(NodeTraversableInterface $node)
{
if (Type::BLOCK != $node->getDocumentType()) {
return false;
}
if (! empty($this->classes)) {
/*** HERE IS THE PROBLEM: ***/
return in_array(get_class($node), $this->classes);
}
return true;
}
}
下面是從我的單元測試方法:
public function testIfContainerBlockIsIncluded()
{
$containerBlock = $this->getMock('Pwn\ContentBundle\Document\ContainerBlock');
$containerBlock->expects($this->any())->method('getDocumentType')->will($this->returnValue(Type::BLOCK));
$filter = new BlockFilter(array('Pwn\ContentBundle\Document\ContainerBlock'));
$this->assertTrue($filter->isIncluded($containerBlock));
}
模擬對象$containerBlock
行爲類似於真實對象Pwn\ContentBundle\Document\ContainerBlock
;甚至使用instanceof
工作的代碼(因爲PHPUnit使它成爲真實類的一個子類,我相信)。
正在測試的代碼使用get_class
獲取該類的字符串值,並將其與預期的類名稱數組進行比較。不幸的是,模擬對象,get_class返回是這樣的:
Mock_ContainerBlock_ac231064
(在_ac231064後綴在每次調用改變)。
這會導致我的測試失敗,那麼我的選擇是什麼?
- 重做代碼以避免使用get_class?這意味着在嘗試編寫可測試代碼時,不應使用get_class。
- 使用ContainerBlock類的實例而不是模擬?這意味着我們正在有效地測試兩個類。
- 其他一些非常聰明的技巧,你都會建議? ;)
感謝您的幫助......
好主意,我認爲這是在我的腦海裏,但實際上它似乎以某種方式使測試「人造」;我不太可能發現測試本身的錯誤。所以我現在想知道這是比使用真實對象而不是模擬更好還是更差... – fazy
@LarsJ我沒有看到任何問題。您的BlockFilter正在測試數組中的類名,因此傳遞Mock的類名是完全沒問題的。在旁註中,我會模擬Interface而不是ContainerBlock,因爲這是IsIncluded所要求的TypeHint。 – Gordon
再次感謝您的所有想法和意見;我已經把它付諸實踐,並且工作正常。 – fazy