PHPUnit - 投掷,捕获和处理自定义异常

时间:2013-02-25 17:38:12

标签: php exception-handling phpunit

我正在尝试在PHP中测试捕获和处理自定义异常。

我已经使用一些额外的属性和方法扩展了基本异常类型。

我正在存根的其中一个类可以抛出异常,我希望能够测试我正确捕获和处理该异常(在这种情况下意味着构建一个响应对象以从调用返回)。

e.g。

try {

    $objectBeingStubbed->doSomething();

} catch (\Exception $ex) {

    if ($ex instanceof CustomExceptionType) {

        $this->_errorResponse->error->message = $exception->getMessage();
        $this->_errorResponse->error->code = $exception->getCode();
        $this->_errorResponse->error->data = $exception->getData();

    } else {

        throw $ex;

    }

}

我试图模拟抛出的异常:

$objectStub->expects($this->any())
           ->method('doSomething')
           ->will($this->throwException(new CustomExceptionType()));

但是当异常到达类中时我正在测试它现在是“Mock_ErrorResponse _ ????”的实例这不会扩展我的自定义异常。我的异常包含在Mock_ErrorResponse的“$ exception”属性中。

有没有办法解决这个问题而不必被迫做一些可怕的事情:

if ($ex instanceof PHPUnit_Framework_MockObject_Stub_Exception) {
    $ex = $ex->exception;
}

if ($ex instanceof CustomExceptionType) {
...

在课堂上我正在测试?

2 个答案:

答案 0 :(得分:3)

首先,改为:

} catch (\Exception $ex) {
    if ($ex instanceof CustomExceptionType) {

你应该使用try / catch结构:

    // (...)
} catch (CustomExceptionType $e) {
    // (...)
} catch (\Exception $e) {
    // (...)
}

所以,回答你的问题,基本上你可能做错了。因为当stubbed方法抛出异常时,它应该抛出你用throwException方法设置的完全异常。

我不知道你是如何构建你的存根的(也许有些东西被破坏了,可能是命名空间)但请考虑下面的一个例子,它可以正常工作。

class Unit
{
    public function foo()
    {
        throw new \InvalidArgumentException();
    }

    public function bar()
    {
        try {
            $this->foo();
        } catch (\InvalidArgumentException $e) {
            return true;
        } catch (\Exception $e) {
            return false;
        }

        return false;
    }
}

class UnitTest extends \PHPUnit_Framework_TestCase
{
    public function testBar()
    {
        $sut = $this->getMock('Unit', array('foo'));
        $sut->expects($this->any())
            ->method('foo')
            ->will($this->throwException(new \InvalidArgumentException()));

        $this->assertTrue($sut->bar());
    }
}

当然,您可以将InvalidArgumentException替换为您自己的实现异常,但这仍然有用。如果您仍然无法弄清楚代码有什么问题,请发布更完整的示例(例如,如何构建存根)。也许那时我可以提供更多帮助。

答案 1 :(得分:1)

现在你可以使用PHPUnit中内置的@expectedException php-doc注释:https://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.exceptions

/**
 * @expectedException InvalidArgumentException
 */
public function testBar()
{
    $sut = $this->getMock('Unit', array('foo'));
    $sut->expects($this->any())
        ->method('foo')
        ->will($this->throwException(new \InvalidArgumentException()));
}