2016-03-01 64 views
3

我正在寫一個基本的PDO包裝類,當我想在我的單元測試中模擬PDOStatement::prepare()使用willThrowException()PDOException的模擬拋出異常時,返回值getMessage()總是和空字符串,而不是我設置的。PHPUnit:嘲諷PDOException-> getMessage()方法

這裏是我試了一下:

// WrapperClass.php 
<?php 

class WrapperClass 
{ 

    private $pdo; 
    private $error = ''; 

    public function __construct(\PDO $pdo) 
    { 
     $this->pdo = $pdo; 
    } 

    public function save() 
    { 
     $sql = 'INSERT INTO ...'; 

     try { 
      $this->pdo->prepare($sql); 

      // some value binding and executing the statement 
     } catch (\PDOException $pdoException) { 
      $this->error = $pdoException->getMessage(); 
     } 
    } 

    public function getError() 
    { 
     return $this->error; 
    } 
} 

和我的測試:

// WrapperClassTest.php 
<?php 

class WrapperClassTest extends \PHPUnit_Framework_TestCase 
{ 

    /** 
    * @test 
    */ 
    public function save_saves_PDOException_message_in_error_property() 
    { 
     $pdoMock = $this->getMockBuilder('WrapperClass') 
         ->disableOriginalConstructor() 
         ->setMethods(['prepare']) 
         ->getMock(); 
     $pdoMock->expects($this->once()) 
       ->method('prepare') 
       ->willThrowException($pdoExceptionMock); 
     $pdoExceptionMock = $this->getMockBuilder('\PDOException') 
         ->setMethods(['getMessage']) 
         ->getMock(); 
     $message = 'Message from PDOException'; 
     $pdoExceptionMock->expects($this->once()) 
       ->method('getMessage') 
       ->willReturn($message); 

     $wrapperClass = new WrapperClass($pdoMock); 
     $wrapperClass->save(); 

     $this->assertEquals($message, $wrapperClass->getError()); 
    } 
} 

我還試圖取代->willThrowException($pdoException)->will($this->throwException($pdoException))但它不工作。

我注意到如果我用替換->willThrowException(new \PDOException('Message from PDOException'))它可以工作,但是我依靠PDOException類而不是嘲笑它。

任何想法?

+0

愚蠢的想法,但聲明的順序可以嗎?你告訴它拋出pdoExceptionMock,但在分配給你的pdoMock後填充數據。 –

回答

2

僅有2語句:

1)在PHP 5.x的所有異常延伸Exception基和it defines '的getMessage' 方法,最終的:

final public string Exception::getMessage (void) 

2)PHPUnit的默默做什麼,當你嘗試模擬final方法(你可以看到代碼生成嘲笑herecanMockMethod返回false最終方法)

所以

->setMethods(['getMessage']) 

沒有效果。

另一方面,您並不需要嘲笑異常,因爲它們是值對象。通過new PDOException('Message from PDOException')非常好。

+0

在這個特定的例子中,不要模擬異常。然而,在Guzzle等您有多個參數的情況下,它會成爲一個問題。 例如RequestException: '公共函數__construct( $消息, RequestInterface $請求, ResponseInterface $響應= NULL, \異常$以前= NULL, 數組$ handlerContext = []' –