2014-12-04 101 views
2

我正在編寫單元測試來模仿可怕的MySql已經消失的錯誤,但我有一個問題讓我的模擬對象正確響應。也許有人可以看到我做錯了什麼。Mocking PDOException類無法響應

private function getMockGoneAway() 
{ 
    $e = $this->getMockBuilder('PDOException') 
     ->disableOriginalConstructor() 
     ->setMethods([ 
      'getMessage', 
      'getCode', 
     ]) 
     ->getMock(); 

    $e->expects($this->any()) 
     ->method('getMessage') 
     ->willReturn('SQLSTATE[HY000]: General error: 2006 MySQL server has gone away'); 

    $e->expects($this->any()) 
     ->method('getCode') 
     ->willReturn('HY000'); 

    return $e; 
} 

這是測試。問題是無論它發生在哪裏,我都無法得到模擬異常以從getMessage或getCode返回預期的結果。

public function testBeginTransactionGoneAway() 
{  
    // get a mock PDO object that overrides beginTransaction method 
    $mock_pdo = $this->getMockPdo(['beginTransaction']); 

    // grab a mock gone-away exception object 
    $mock_gone_away_exception = $this->getMockGoneAway(); 

    die("MSG: ".$mock_gone_away_exception->getMessage()); 

    // setup mock pdo responses 
    $mock_pdo->expects($this->once()) 
     ->method('beginTransaction') 
     ->will($this->throwException($mock_gone_away_exception)); 

    $this->db->replaceConnection($mock_pdo); 
    $this->db->begin(); 
} 

回答

2

所以我想通了。基本異常類聲明getMessage和getCode是最終的。出於某種原因,PHPUnit不會讓你知道它不能重寫這些方法。所以就像使用模擬PDO類一樣,您也需要手動模擬PDOException類。

class MockPDOException extends \PDOException 
{ 
    public function __construct($msg, $code) { 
     $this->message = $msg; 
     $this->code = $code; 
    } 
} 

現在你可以模仿例外正確

$mock_gone_away_exception = new MockPDOException('SQLSTATE[HY000]: General error: 2006 MySQL server has gone away','HY000'); 

// setup mock pdo responses 
$mock_pdo->expects($this->once()) 
    ->method('beginTransaction') 
    ->will($this->throwException($mock_gone_away_exception)); 

所以這很有趣。每天學習更多關於PHPUnit的知識。歡迎評論爲什麼這是一個壞主意。