2011-03-16 82 views
13

使用PHPUnit,我嘲笑pdo,但我試圖找到一種方法來準備多個數據庫查詢語句。在phpunit中,有沒有類似於onconsecutivecalls方法在「with」方法中使用的方法?

$pdo = $this->getPdoMock(); 
$stmt = $this->getPdoStatementMock($pdo); 

$pdo->expects($this->any()) 
    ->method('prepare') 
    ->with($this->equalTo($title_query)) 
    ->will($this->returnValue($stmt)); 

$title_stmt = $pdo->prepare($title_query); 
$desc_stmt = $pdo->prepare($desc_query); 

我想通過類似onConsecutiveCalls爲「與」法的東西,所以我可以準備多個語句,如上面看到的。 你會如何去做這件事?

回答

19

您可以用$this->at()代替$this->any()編寫單獨的預期相匹配的相同方法連續調用:

$pdo->expects($this->at(0)) 
    ->method('prepare') 
    ->with($this->equalTo($title_query)) 
    ->will($this->returnValue($stmt)); 

$pdo->expects($this->at(1)) 
    ->method('prepare') 
    ->with($this->equalTo($desc_query)) 
    ->will($this->returnValue($stmt)); 

$title_stmt = $pdo->prepare($title_query); 
$desc_stmt = $pdo->prepare($desc_query); 
+0

完美!這就是我一直在尋找的。現在工作很好。謝謝! – 2011-03-16 17:39:44

+6

請注意,該計數器是根據接收到的所有*方法調用進行的每個模擬。因此,如果將有兩個到'$ pdo'的中間調用,則可以使用0和3。 – 2011-03-16 20:37:20

+0

@大衛是的,你是對的。還值得一提的是,只需要調用實際被替換爲模擬實現計數的方法。 – Vika 2011-03-16 20:55:37

3

我發現類似的唯一的事情,你問的是使用「在」什麼:

$mock->expects($this->at(0))->method // etc 
$mock->expects($this->at(1))->method // etc 

所以你設置的第一次它被稱爲(0)的預期,第二個時間等。

+0

完美!這正是我需要的。謝謝! – 2011-03-16 17:37:23

0

幾個人已經指出,在($指數)可以用於通話的具體實例一種方法。 David H.和Vika澄清說,$ index計數對所有對象的模擬方法的所有調用。

此外,值得注意的是,PHPunit文檔的Test Doubles Chapter對此有警告。它指出,使用at()應謹慎使用,因爲它可能會導致脆弱的測試,這些測試過多依賴於具體的實現。

14

PHPUnit 4.1有一個新方法withConsecutive()。從Test Double Chapter

class FooTest extends PHPUnit_Framework_TestCase 
{ 
    public function testFunctionCalledTwoTimesWithSpecificArguments() 
    { 
     $mock = $this->getMock('stdClass', array('set')); 
     $mock->expects($this->exactly(2)) 
      ->method('set') 
      ->withConsecutive(
       array($this->equalTo('foo'), $this->greaterThan(0)), 
       array($this->equalTo('bar'), $this->greaterThan(0)) 
      ); 

     $mock->set('foo', 21); 
     $mock->set('bar', 48); 
    } 
} 

withConsecutive()每個參數爲一個呼叫到指定的方法。

9

使用更新版本的PHPUnit,接受的答案可以簡化很多。

另外,儘管它與原始問題並不直接相關,但可以通過willReturnOnConsecutiveCalls方法輕鬆地爲每個方法調用提供不同的返回值。

$pdo->expects($this->exactly(2)) 
    ->method('prepare') 
    ->withConsecutive(
     $this->equalTo($title_query), 
     $this->equalTo($desc_query) 
    ) 
    ->willReturnOnConsecutiveCalls(
     $stmt, // returned on the 1st call to prepare() 
     $stmt // returned on the 2nd call to prepare() 
    ); 
+1

這是一個更合適,更簡單回答最新的PHPUnit版本,絕對容易。 – 2016-08-11 12:10:56

0

我用一個數據提供程序,需要執行的查詢,我可以用它來填充我的供應商的數量變化,我想提供應執行的查詢的數組。 withConsecutive的問題在於它需要可變數量的數組,每個數組都是一個參數數組。

我解決它使用的follwing代碼,這種感覺「哈克」,但工作:

$withConsecutiveArgs = [ 
    [$this->equalTo($title_query)], 
    [$this->equalTo($desc_query)], 
    ..., 
    N queries 
]; 
$withConsecutiveReturns = [ 
    $title_stmt, 
    $desc_stmt, 
    ..., 
    N returns 
]; 

$methodMock = $pdo->expects($this->exactly(count($args))->method('prepare'); 
$methodMock->getMatcher()->parametersMatcher = new \PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters($withConsecutiveArgs); 
$methodMock->will(new \PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($withConsecutiveReturns)); 

$title_stmt = $pdo->prepare($title_query); 
$desc_stmt = $pdo->prepare($desc_query); 
... 
$N_s_stmt = $pdo->prepare($N_s_query); 

我希望它在PHPUnit(這是不確定的未來版本正確的發展,因爲我依靠的內部lib,但這是做單元測試的重點,我可能不得不重構它,但生產不會因此而受到影響)

相關問題