2014-09-12 143 views
4

我有一个类来处理错误,包括异常。如果发现异常,我会将异常作为参数传递给我的异常/错误处理程序。PHPUnit模拟异常

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(); 

有一个变通嘲笑异常或我只是做错了什么?

+1

是您的对象抛出异常称为? 否则,您可以生成该模拟,但如果没有引发它,或者您不生成该条件,则该模拟不会发生。 是否可以显示所有的代码,或者至少是该代码的代码?, 自2011年以来,我一直没有与phpunit一起工作,所以记住这一点,但我的头顶,我记得你有一个装饰器来捕获一个预期的异常,但你的情况似乎有点不同,你正在产生一个模拟,但是(这是我的假设),你没有产生抛出异常本身的条件,所以你的断言会失败。 – 2014-09-13 03:10:25

回答

5

返回错误详细信息(如getFile()等)的Exception类方法被定义/声明为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. 

正如在这里看到:https://phpunit.de/manual/current/en/test-doubles.html

+0

解决方法的任何想法? – 2015-07-29 09:17:43

+0

我以为你可以创建一个实现异常类的虚拟类。在这个函数中,当调用时你会明确地抛出一个错误,这样你就可以知道确切的文件,行号等。使用测试用例调用函数并捕获抛出的显式异常,声明文件,行号等正确。 – antoniovassell 2015-08-01 00:33:29

0

这是一个黑客攻击的一位,但尝试添加像这样到你的TestCase:

/** 
* @param object $object  The object to update 
* @param string $attributeName The attribute to change 
* @param mixed $value   The value to change it to 
*/ 
protected function 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(),因此我认为这并不重要。

它也是有用的,当你测试一个异常是如何处理的,例如是否有其他方法(如记录器)与异常消息作为参数