2013-01-04 84 views
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類的實例而不是模擬?這意味着我們正在有效地測試兩個類。
  • 其他一些非常聰明的技巧,你都會建議? ;)

感謝您的幫助......

回答

2

在檢驗合格素的類名:

new BlockFilter(array(get_class($this->containerBlock))); 
+0

好主意,我認爲這是在我的腦海裏,但實際上它似乎以某種方式使測試「人造」;我不太可能發現測試本身的錯誤。所以我現在想知道這是比使用真實對象而不是模擬更好還是更差... – fazy

+0

@LarsJ我沒有看到任何問題。您的BlockFilter正在測試數組中的類名,因此傳遞Mock的類名是完全沒問題的。在旁註中,我會模擬Interface而不是ContainerBlock,因爲這是IsIncluded所要求的TypeHint。 – Gordon

+1

再次感謝您的所有想法和意見;我已經把它付諸實踐,並且工作正常。 – fazy

相關問題