我正在编写一个基本的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;
}
}
和我的测试:
// 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($pdoException)
替换为->willThrowException(new \PDOException('Message from PDOException'))
,那么它可以正常工作,但我依靠PDOException
类而不是嘲笑它。
有什么想法吗?
答案 0 :(得分:3)
只有2个陈述:
1)PHP 5.x中的所有异常都扩展了基本异常和it defines&#39; getMessage&#39;最后的方法:
final public string Exception::getMessage ( void )
2)当您尝试模拟最终方法时,PHPUnit会默默地执行任何操作(您可以看到生成模拟here的代码,canMockMethod
为最终方法返回false)
所以
->setMethods(['getMessage'])
没有效果。
另一方面,你并不需要模拟异常,因为它们是价值对象。传递new PDOException('Message from PDOException')
非常好。