2014-12-04 98 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的知识。欢迎评论为什么这是一个坏主意。