使用 PHPUnit 测试受保护方法的最佳实践(在抽象类上) [英] Best practices to test protected methods with PHPUnit (on abstract classes)

查看:22
本文介绍了使用 PHPUnit 测试受保护方法的最佳实践(在抽象类上)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 PHPUnit 和 PHP >= 5.3 可以测试受保护的方法.stackoverflow 的以下页面概述了最佳实践:

使用 PHPUnit 测试受保护方法的最佳实践"

受保护的静态函数 callProtectedMethod($name, $classname, $params) {$class = new ReflectionClass($classname);$method = $class->getMethod($name);$method->setAccessible(true);$obj = new $classname($params);返回 $method->invokeArgs($obj, $params);}

使用 PHPUnit 可以轻松测试抽象类上的公共方法.使用上述方法可以很容易地在普通类上测试受保护的方法.必须以某种方式测试抽象类上的受保护方法......

我知道 PHPUnit 派生抽象类并在具体类中实现"抽象方法,并针对该具体类触发测试 - 但我不知道如何将其集成到上述方法中以获得 callProtectedMethodOnAbstractClasses().

您如何进行此类测试?

PS:问题不在于测试受保护方法的真实性(请参阅:白盒、灰盒和黑盒测试).测试受保护方法的需要取决于您的测试策略.

解决方案

既然您要求的是最佳实践",我将采取不同的方法来回答:

不要测试受保护和私有的方法

仅仅因为你可以并不意味着你应该.

您想测试一个类是否有效.这意味着您可以调用的所有函数(所有公共的)返回正确的值(并且可能在传入的对象上调用正确的函数)什么都没有否则.

你不关心这是如何在类中实现的.

恕我直言,出于两个重要原因,为任何非公开内容编写测试甚至会伤害您:

  • 时间

编写测试需要更长的时间,因为您需要更多,而重构也需要更长的时间.如果您在类中移动代码而不更改其行为,则不需要更新其测试.测试应该告诉你一切仍然有效!

  • 有意义的代码覆盖率

如果您为每个丢失的受保护方法编写测试,那么您会从代码覆盖率报告中继承一个好处:它不会告诉您不再调用哪些受保护的函数.这是(恕我直言)一件坏事,因为您要么没有正确测试所有公共方法(为什么在测试每个案例时都不会调用一个方法?)或者您真的不需要该方法 但既然它是绿色"的,你就不用再考虑了.

引用 PHPUnit 作者

<块引用>

所以:仅仅因为可以测试受保护和私有的属性和方法并不意味着这是一件好事".

http://sebastian-bergmann.de/archives/881-测试您的隐私.html

因为现实世界有时会有所不同

...->setAccessible() 适用于普通方法

对于抽象的东西使用 ...->getMockForAbstractClass()

但请仅在确实必要时才这样做.

抽象类中的受保护方法将通过测试其子类的公共 api 来测试,无论如何,应用我的上述参数.

With PHPUnit and PHP >= 5.3 it is possible to test protected methods. The following page at stackoverflow outlined the best practice on it:

"Best practices to test protected methods with PHPUnit"

protected static function callProtectedMethod($name, $classname, $params) {
  $class = new ReflectionClass($classname);
  $method = $class->getMethod($name);
  $method->setAccessible(true);
  $obj = new $classname($params);
  return $method->invokeArgs($obj, $params);
}

To test public methods on abstract classes is easy with PHPUnit. To test protected methods on normal classes is easy with approach above. To test protected methods on abstract classes must be possible somehow...

I know PHPUnit derives abstract classes and "implements" abstract methods in a concrete class and fires the tests against that concrete class - but i do not know how to integrate that into the approach above to have a callProtectedMethodOnAbstractClasses().

How are you doing such tests?

PS: The question is NOT about the truth of testing protected methods (see: white-, gray- and blackbox-testing). The need of testing protected methods depends on your test strategy.

解决方案

Since you are asking for a 'best practice' I'll take a different approach to answer:

Don't test protected and private methods

Just because you can doesn't mean you should.

You want to test that a class works. That means that all the functions you can call on it (everything public) return the right values (and maybe call the right functions on objects passed in) and nothing else.

You don't care how this is implemented in the class.

Imho it is even hurting you to write test for anything non-public for two big reasons:

  • Time

Writing tests takes longer as you need more and refactoring also takes longer. If you move around code in a class without changing its behavior you shoudn't be required to update its tests. The tests should tell you that everything still works!

  • Meaningful code coverage

If you write a test for every protected method you loose one inherit benefit from the code coverage report: It won't tell you which protected functions aren't call anymore. That is (imho) a bad thing because you either don't test all the public methods correctly (why is there a method that isn't called if you test every case?) or you really don't need that method anymore but since it's "green" you don't give it a second thought.

To quote the PHPUnit Author

So: Just because the testing of protected and private attributes and methods is possible does not mean that this is a "good thing".

http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html

Since the real world sometimes differs

...->setAccessible() is fine for normal methods

for abstract stuff use ...->getMockForAbstractClass()

But please do so only if it is really necessary.

A protected method in an abstract class will get tested by testing the public api of its children anyway with my arguments from above applying.

这篇关于使用 PHPUnit 测试受保护方法的最佳实践(在抽象类上)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆