我不一定要寻找具体涉及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
希望这能帮助到不同情况下的人。