PHPUnit:模拟 PDOException->getMessage() 方法

Hub*_*0xx 3 php phpunit exception mocking

我写一个基本的PDO包装类,当我想以模拟异常抛出的PDOStatement::prepare()使用willThrowException()与模拟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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和我的测试:

// 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());
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试替换为->willThrowException($pdoException)->will($this->throwException($pdoException))但它不起作用。

我注意到如果我->willThrowException($pdoException)->willThrowException(new \PDOException('Message from PDOException'))它替换它是有效的,但是我依赖于这个PDOException类而不是嘲笑它。

有任何想法吗?

Nik*_* U. 5

仅2个声明:

1) PHP 5.x 中的所有异常都扩展了 base Exception 并将'getMessage' 方法定义为 final:

final public string Exception::getMessage ( void )
Run Code Online (Sandbox Code Playgroud)

2)PHPUnit的默默一筹莫展的时候,你尝试嘲笑最终方法(你可以看到,生成模拟考试代码在这里canMockMethod返回false最终方法)

所以

->setMethods(['getMessage'])
Run Code Online (Sandbox Code Playgroud)

没有效果。

另一方面,您实际上不需要模拟异常,因为它们是值对象。过关new PDOException('Message from PDOException')还算可以。