PHPUnit:模拟 PDOException->getMessage() 方法
PHPUnit: Mocking PDOException->getMessage() method
我正在编写一个基本的 PDO 包装器 class,当我想通过 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());
}
}
我也试过用->will($this->throwException($pdoException))
替换->willThrowException($pdoException)
,但是没用。
我注意到,如果我将 ->willThrowException($pdoException)
替换为 ->willThrowException(new \PDOException('Message from PDOException'))
它会起作用,但我依赖 PDOException
class 而不是模拟它。
有什么想法吗?
只有 2 个语句:
1) PHP 5.x 中的所有异常都将基本异常和 it defines 'getMessage' 方法扩展为最终的:
final public string Exception::getMessage ( void )
2) PHPUnit 在您尝试模拟 final 方法时静默不执行任何操作(您可以看到为 final 生成模拟 here、canMockMethod
returns false 的代码方法)
所以
->setMethods(['getMessage'])
没有效果。
另一方面,您实际上不需要模拟异常,因为它们是值对象。通过new PDOException('Message from PDOException')
就可以了。
我正在编写一个基本的 PDO 包装器 class,当我想通过 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());
}
}
我也试过用->will($this->throwException($pdoException))
替换->willThrowException($pdoException)
,但是没用。
我注意到,如果我将 ->willThrowException($pdoException)
替换为 ->willThrowException(new \PDOException('Message from PDOException'))
它会起作用,但我依赖 PDOException
class 而不是模拟它。
有什么想法吗?
只有 2 个语句:
1) PHP 5.x 中的所有异常都将基本异常和 it defines 'getMessage' 方法扩展为最终的:
final public string Exception::getMessage ( void )
2) PHPUnit 在您尝试模拟 final 方法时静默不执行任何操作(您可以看到为 final 生成模拟 here、canMockMethod
returns false 的代码方法)
所以
->setMethods(['getMessage'])
没有效果。
另一方面,您实际上不需要模拟异常,因为它们是值对象。通过new PDOException('Message from PDOException')
就可以了。