模拟PDOException类无法响应

时间:2014-12-04 02:17:59

标签: php mysql unit-testing mocking phpunit

我正在编写一个单元测试来模仿可怕的MySql已经消失了,但我有一个问题,我的模拟对象正确响应。也许有人可以看到我做错了什么。

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();
}

1 个答案:

答案 0 :(得分:3)

所以我想出来了。基本异常类将getMessage和getCode声明为final。出于某种原因,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的更多信息。欢迎评论为什么这是一个坏主意。