2013-04-24 64 views
2

這裏是下面的代碼示例與()功能PHPUnit的模擬工作怪異

<?php 

interface iFS 
{ 
    public function read(); 
    public function write($data); 
} 

class MyClass 
{ 
    protected $_fs = null; 

    public function __construct(iFS $fs) 
    { 
     $this->_fs = $fs; 
    } 

    public function run(array $list) 
    { 
     foreach ($list as $elm) 
     { 
      $this->_fs->write($elm); 
     } 

     return $this->_fs->read(); 
    } 
} 

class MyTests extends PHPUnit_Framework_TestCase 
{ 
    public function testFS() 
    { 
     $mock = $this->getMock('iFS'); 
     $mock->expects($this->at(0)) 
       ->method('read') 
       ->will($this->returnValue('tototatatiti')); 

     $c = new MyClass($mock); 
     $result = $c->run(array('toto', 'tata', 'titi')); 

     $this->assertEquals('tototatatiti', $result); 
    } 
} 

這絕對不是一個真實的案例,但它使發生一些奇怪的使用PHPUnit和($指數)功能。

我的問題很簡單,是正常的測試失敗?

我明確地要求歸還 「tototatatiti」,但它從來沒有發生......

  • 我刪除行$本 - > _ FS->寫($榆樹); 或
  • 我替換$模擬轉>預計($這 - >在(0))由$模擬轉>預計($這 - >一次())

該測試通到綠色

有什麼我不明白的嗎?

編輯:

$模擬轉>預計($這 - >在(3)) - >方法( '讀') - >將($這 - >的returnValue( 'tototatatiti')) ;

=>將通過測試的綠色......

+0

看來,這 - $>在($指數)功能並不適用於方法指定,但對整個嘲笑的對象......如果這是正確的,這是完全無用的! – nemenems 2013-04-24 15:13:01

回答

0

我認爲在PHPUnit的()功能不有用存根不同的返回結果爲一個模擬的方法,如果嘲笑對象包含一些其他的方法女巫呼叫過於...

如果你想測試是這樣的:

$stub->expects($this->at(0)) 
       ->method('read') 
       ->will($this->returnValue("toto")); 

$stub->expects($this->at(1)) 
       ->method('read') 
       ->will($this->returnValue("tata")); 

你應該更好地利用類似

$stub->expects($this->exactly(2)) 
       ->method('read') 
       ->will($this->onConsecutiveCalls("toto", "tata)); 
3

根據PHPUnit source code我們:

public function matches(PHPUnit_Framework_MockObject_Invocation $invocation) 
{ 
    $this->currentIndex++; 

    return $this->currentIndex == $this->sequenceIndex; 
} 

每次PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex嘗試匹配的調用,受保護的變量$currentIndex遞增,因此首先寫入的電話會使其變爲0,然後與read不匹配。

第二呼叫,以使read成爲1的值,所以它不任一匹配。

看起來它確實適用於整個對象,如果您需要確保按特定順序發生一系列調用,這非常有用。

舉例來說,假設write方法只調用一次,你可以有這樣的:

$mock->expects($this->at(0)) 
      ->method('write'); 

$mock->expects($this->at(1)) 
      ->method('read') 
      ->will($this->returnValue('tototatatiti')); 

這確保了write方法是read方法之前確實叫。