Exception PHPUnit模拟异常
我有一个类处理错误,包括异常。如果捕获到异常,我将把异常作为参数传递给我的异常/错误处理程序Exception PHPUnit模拟异常,exception,error-handling,phpunit,Exception,Error Handling,Phpunit,我有一个类处理错误,包括异常。如果捕获到异常,我将把异常作为参数传递给我的异常/错误处理程序 try { someTrowingFnc(); } catch (\Exception $e) { this->error->exception($e); } 现在我想对这个错误处理程序进行单元测试并模拟异常 我发现很难模拟异常,以便控制异常消息、文件和行 $exceptionMock = $this->getMock('Exception', array(
try {
someTrowingFnc();
} catch (\Exception $e) {
this->error->exception($e);
}
现在我想对这个错误处理程序进行单元测试并模拟异常
我发现很难模拟异常,以便控制异常消息、文件和行
$exceptionMock = $this->getMock('Exception', array(
'getFile',
'getLine',
'getMessage',
'getTrace'
)); // Tried all mock arguments like disable callOriginalConstructor
$exceptionMock->expects($this->any())
->method('getFile')
->willReturn('/file/name');
$exceptionMock->expects($this->any())
->method('getLine')
->willReturn('3069');
$exceptionMock->expects($this->any())
->method('getMessage')
->willReturn('Error test');
下面代码的结果总是返回NULL
$file = $exception->getFile();
$line = $exception->getLine();
$msg = $exception->getMessage();
是否有办法模拟异常,或者我只是做错了什么?返回错误详细信息的异常类方法(如
getFile()
等)被定义/声明为final
方法。这是PHPUnit目前在模拟受保护、私有和最终的方法时的一个限制
Limitations
Please note that final, private and static methods cannot be stubbed or mocked. They are ignored by PHPUnit's test double functionality and retain their original behavior.
如图所示:这有点像黑客,但请尝试在测试用例中添加类似的内容:
/**
*@param object$object要更新的对象
*@param string$attributeName指定要更改的属性
*@param mixed$value要将其更改为的值
*/
受保护的函数setObjectAttribute($object、$attributeName、$value)
{
$reflection=new\ReflectionObject($object);
$property=$reflection->getProperty($attributeName);
$property->setAccessible(true);
$property->setValue($object,$value);
}
现在您可以更改这些值
$exception=$this->getMock('exception');
$this->setObjectAttribute($exception,'file','/file/name');
$this->setObjectAttribute($exception,'line',3069);
$this->setObjectAttribute($exception,'message','Error test');
当然,您还没有真正模拟该类,不过如果您有更复杂的自定义异常,这仍然很有用。此外,您无法计算该方法被调用的次数,但由于您使用的是$this->any()
,因此我认为这并不重要
当您测试如何处理异常时,它也很有用,例如查看是否调用了另一个方法(如记录器),并将异常消息作为参数PHPUnit TestCase类中的throwException()可以将Throwable的任何实例作为参数
下面是一个示例,如果您在FileWriterToBeTested中有try/catch,则该示例应通过,如果您没有try/catch,则该示例将失败:
$this->reader = $this->getMockBuilder(Reader::class)->getMock();
$this->reader->method('getFile')->will(static::throwException(new \Exception()));
$file = new FileWriterToBeTested($this->reader);
static::assertNull($file->getFile('someParamLikePath'));
测试类样本:
class FileWriterToBeTested
{
/**
* @var Reader
*/
private $reader;
public function __construct(Reader $reader): void
{
$this->reader = $reader;
}
/**
* @return Reader
*/
public function getFile(string $path): void
{
try {
$this->reader->getFile($path);
} catch (\Exception $e) {
$this->error->exception($e);
}
}
}
您的对象是否正在引发异常?否则,您可以生成该模拟,但如果没有任何东西抛出它,或者您没有生成该条件,则该模拟不会发生。有可能显示所有的代码,或者至少是类的代码吗?我从2011年起就没有使用过phpunit,所以请记住,但在我的脑海中,我记得您有一个装饰程序来捕获预期的异常,但是您的情况似乎有点不同,您正在生成一个模拟,但是(这是我的假设),您没有生成引发异常本身的条件,因此您的断言将失败。我认为您可以创建一个虚拟类来实现您的异常类。在该函数中,您将在调用时显式抛出错误,这样您将知道确切的文件、行号等。使用测试用例调用该函数并捕获抛出的显式异常,断言文件、行号等是正确的。