2015-04-07 28 views
0

類:PHPUnit的,模擬的,willReturnCallback()犯規預期工作

class TestMe 
{ 
    public function m1 (array &$a) 
    { 
    } 

    public function m2 (array &$a) 
    { 
    } 

    public function methodd() 
    { 
     $a = array(); 
     $this->m1 ($a); 
     $this->m2 ($a); 
     return $a; 
    } 
} 

測試:

class X extends PHPUnit_Framework_TestCase 
{ 
    public function testMethod() 
    { 
     $mock = $this->getMock('TestMe', array('m1','m2')); 
     $mock->expects($this->once())->method('m1')->with(array())->willReturnCallback(function (&$x) { $x['a'] = 1; }); 
     $mock->expects($this->once())->method('m2')->with(array('a' => 1))->willReturnCallback(function (&$x) { $x['b'] = 2; }); 

     $x = $mock->methodd(); 

     $this->assertEquals (array('a' => 1, 'b' => 2), $x); 
    } 
} 

莫名其妙地失敗:

有1失敗:

1 )X :: testMethod 方法名稱的期望失敗等於調用1次(s)時。 調用TestMe :: m1(Array(...))的參數0與預期值不匹配。 失敗斷言兩個數組是相等的。 ---預期 +++實際 @@ @@ 陣列( + '一個'=> 1 + 'B'=> 2 )

FAILURES! 測試:1,斷言:2,失敗:1.

我不知道它可能是什麼。換句話說,我想修改一個「參考」參數,並檢查它:)

回答

1

問題不是直接與willReturnCallback()。你的問題是,你通過引用傳遞事物。如果查看失敗消息,它會告訴您傳入方法m1的參數與預期的不符。這是說陣列不是空的。

PHPUnit在運行測試後檢查模擬參數調用。所以它存儲了方法調用中使用的參數的副本。在你的回調中,你指的是變量的引用。所以PHPUnit在模擬中存儲自己的引用副本以進行檢查。在對函數進行後續調用時,變量不僅會被更新,而且會被PHPUnit存儲的值。因此,當它檢查使用正確的參數調用了模擬時,它會檢查存儲在參考中的值(最終值而不是最初使用的值)。

爲了解決這個問題,改變你的測試:

public function testMethod() 
{ 
    //Get a copy of the testcase to use in the callback 
    $testcase = $this; 
    $mock = $this->getMock('TestMe', array('m1','m2')); 
    $mock->expects($this->once()) 
     ->method('m1') 
     ->willReturnCallback(function (&$x) use ($testcase) { 
      //do your parameter checking immediately 
      $testcase->assertEquals(array(), $x); 
      $x['a'] = 1; 
     }); 
    $mock->expects($this->once()) 
     ->method('m2') 
     ->willReturnCallback(function (&$x) use ($testcase) { 
      //do your parameter checking immediately 
      $testcase->assertEquals(array('a' => 1), $x); 
      $x['b'] = 2; 
     }); 

    $x = $mock->methodd(); 

    $this->assertEquals (array('a' => 1, 'b' => 2), $x); 
} 

雖然海事組織,你不應該嘲笑代碼,您正在測試類的一部分。 methodd()使用這些函數的事實是您的類的實現細節。如果您決定將m1()m2中找到的邏輯轉換爲methodd(),則應通過測試。讓這些方法受到嘲笑使得你的測試不太有用。由於類中的代碼更改而不是功能/錯誤的實際更改,它們可能會失敗。

無論如何,解決您的具體問題是檢查回調中的參數值,而不是使用with()