最佳做法,以测试保护的方法进行[关闭]
-
05-07-2019 - |
解决方案
如果你使用PHP5(>=5.3.2)与进行中,可以测试你的私人和受保护的方法通过利用反射让它们以公开之前的运行测试:
protected static function getMethod($name) {
$class = new ReflectionClass('MyClass');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function testFoo() {
$foo = self::getMethod('foo');
$obj = new MyClass();
$foo->invokeArgs($obj, array(...));
...
}
其他提示
你似乎知道了,但我只想重申,它无论如何;这是一个不好的兆头,如果你需要测试的保护方法。其目的的一个单元的测试,以测试的界面类、和保护的方法实施细节。这就是说,在一些情况下,它才有意义。如果您使用的继承,可以看到一个超类提供一个界面对的子类。因此,在这里,你会必须测试的保护的方法(但从来没有一个 私 一个)。解决这个,是创建一个子类的测试目的,使用这个来获得的方法。例如:
class Foo {
protected function stuff() {
// secret stuff, you want to test
}
}
class SubFoo extends Foo {
public function exposedStuff() {
return $this->stuff();
}
}
注意,你总是可以替换继承与组成。测试时代,通常很容易处理的代码使用这一模式,因此可能需要考虑这一选择。
teastburn 有正确的方法。甚至更简单的是调用的方法直接返回答:
class PHPUnitUtil
{
public static function callMethod($obj, $name, array $args) {
$class = new \ReflectionClass($obj);
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method->invokeArgs($obj, $args);
}
}
你能叫这只是你的试验:
$returnVal = PHPUnitUtil::callMethod(
$this->object,
'_nameOfProtectedMethod',
array($arg1, $arg2)
);
我想建议一个微小的变化,以getMethod()定义 uckelman的答案.
这个版本的变化getMethod()通过消除硬编码的价值观和简化使用一点。我建议你将它添加到你的PHPUnitUtil类如下例所示或要你PHPUnit_Framework_TestCase延伸类(或者,我假设,在全球范围内你PHPUnitUtil文件)。
由于MyClass正在实例反正ReflectionClass可以采取一串或一个对象...
class PHPUnitUtil {
/**
* Get a private or protected method for testing/documentation purposes.
* How to use for MyClass->foo():
* $cls = new MyClass();
* $foo = PHPUnitUtil::getPrivateMethod($cls, 'foo');
* $foo->invoke($cls, $...);
* @param object $obj The instantiated instance of your class
* @param string $name The name of your private/protected method
* @return ReflectionMethod The method you asked for
*/
public static function getPrivateMethod($obj, $name) {
$class = new ReflectionClass($obj);
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
// ... some other functions
}
我还创建了一个别功能getProtectedMethod()以明确的期望是什么,但是,一个是给你的。
干杯!
我认为troelskn被关闭。我会做这个而不是:
class ClassToTest
{
protected testThisMethod()
{
// Implement stuff here
}
}
然后,实施这样的事情:
class TestClassToTest extends ClassToTest
{
public testThisMethod()
{
return parent::testThisMethod();
}
}
你然后,运行测试对TestClassToTest.
它应该是能够自动产生这种扩展类通过分析代码。我不会感到惊讶,如果进行已经提供了这样一个机制(虽然我还没有检查).
我要扔我的帽子进入环在这里:
我用__叫哈克与混合度的成功。替我了是使用游客的模式:
1:产生stdClass或定义类(强制执行的类型)
2:总理与所需的方法和参数
3:确保你被测系统有一个acceptVisitor方法,它将执行的方法与指定参数在访类
4:它注入课你想要测试
5:被测系统注入的结果作为访客
6:运用你的测试条件下的到访问的结果属性
你的确可以使用__称()一般形式要接受保护的方法。能够测试这个类
class Example {
protected function getMessage() {
return 'hello';
}
}
你创建的一个子类ExampleTest.php:
class ExampleExposed extends Example {
public function __call($method, array $args = array()) {
if (!method_exists($this, $method))
throw new BadMethodCallException("method '$method' does not exist");
return call_user_func_array(array($this, $method), $args);
}
}
注意__呼吁()方法并没有参照类在任何方式这样你可以复制的上述各类受保护的方法你想测试和更改类声明。你可以把这种功能在一个共同的基类,但是我还没有尝试过。
现在测试的情况下本身的唯一不同之处在其中你建造的对象来进行检验,交换在ExampleExposed的例子。
class ExampleTest extends PHPUnit_Framework_TestCase {
function testGetMessage() {
$fixture = new ExampleExposed();
self::assertEquals('hello', $fixture->getMessage());
}
}
我相信PHP5.3允许使用反映改变的无障碍的方法是直接的,但我认为你必须这样做对于每种方法的独立。
我建议下列解决方法"亨里克*保罗"'s解决方法/想法:)
你知道名字的私法类。例如,他们都喜欢_add(),_edit(),_delete()等。
因此,当你想要测试它方面的单元的测试,只需拨打私人的方法通过的前缀和/或suffixing一些 常见的 词(例如_addPhpunit)使当__呼吁()方法(由于方法_addPhpunit()不存在)的所有人类,你只是把必要的代码,在__呼吁()方法除去的前缀/后缀字/s(进行),然后以电话,推导出私人的方法。这又是一个很好的使用魔法的方法。
尝试。