2016-03-01 67 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 = []' –