PHPUnit和抛出异常使用反射



我不一定要寻找具体涉及Reflection的答案,任何答案都可以。

我有下面的抽象类,它是由另一个类扩展的:

abstract class A_Class{
    protected function returnSomething(array $param = ['some_argument' => false])
    {
        if(!is_bool($param))
        {
            throw new Exception('some message goes here');
        }
    }
}
class B_Class extends A_Class{}

我用的是PHPUnit 4.8.27 by Sebastian Bergmann and contributors.

我有以下测试

/**
 * @expectedException Exception
 */
public function testException()
{
    $method = new ReflectionMethod(B_Class::class, 'returnSomething');
    $method->setAccessible(true);
    $method->invokeArgs(new B_Class(), ['some_argument' => 'string']);
}

运行测试时,出现以下消息:

Failed asserting that exception of type "Exception" is thrown.

我谷歌了一下,我真的找不到答案,我做错了什么。老实说,我甚至不确定我做错了什么。问题本身可能不是我的代码,因为它是与Reflection类。我对它了解不多,所有的文档都有点缺乏。它可能无法抛出在反射类中定义的异常。

如能指点,不胜感激。


我已经试过了:

使用ReflectionClass代替ReflectionMethod:

/**
 * @expectedException Exception
 */
public function testGetExcerptException()
{
    $method = new ReflectionClass(new B_Class()::class);
    $methodToCall = $method->getMethod('returnSomething');
    $methodToCall->setAccessible(true);
    $methodToCall->invokeArgs(new B_Class(), ['some_argument' => 'string']);
}

将可见性设置为public,这当然有效,但这有点违背目的。


如果有人遇到这个问题。不要像我那样。甚至写PHPUnit的人都说这是个坏主意。所有被测试的方法都应该是公共的

使用Reflection的另一种解决方案是使用MockObjects,因为您正在使用PHPUnit。PHPUnit中的mock允许您模拟类的任何公共和受保护方法。

我发现了这个问题,试图找出为什么我的ReflectionClass不"通过";异常(结果是代码中没有throw,我的下级同事刚刚使用了http_response_code(404); exit;)。

但是无论如何,我发现了另一种有趣的方法来做到这一点,因为PhpUnit MockObjects现在不支持调用受保护的方法:

请注意final、private、protected和static方法不能被stub或mock。它们将被PHPUnit的test double功能忽略,并保持其原始行为。

(见https://phpunit.de/manual/6.5/en/test-doubles.html)

可以通过模拟/扩展原始类并创建新的公共方法来调用受保护的类来实现。这样做不会影响任何现有的代码(比如添加一些"onlyForTests")。

(见https://www.w3docs.com/snippets/php/best-practices-to-test-protected-methods-with-phpunit.html)

本文引用的是PhpUnit,但这个可以单独完成。下面是我简单写的例子:

(new class extends OriginalClass {                // creating new mock object...
    public function myMockMethod($param): void {  // with public method defined...
        $this->originalProtectedMethod($param);   // to recall the protected method
    }
})->myMockMethod('value');                        // calling the public mock method

希望这能帮助到不同情况下的人。

相关内容

  • 没有找到相关文章

最新更新