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

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

问题描述

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

使用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);
}

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

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

您如何进行此类测试?

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

解决方案

由于您要寻求最佳实践",因此我将采用另一种方法来回答:

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

仅仅因为您不能代表您应该这样做.

您要测试某个类是否有效.这意味着您可以调用它的所有函数(所有公共对象)返回正确的值(并且可以对传入的对象调用正确的函数)其他.

您并不关心在课堂上如何实现这一点.

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

  • 时间

笔试需要更长的时间,重构也需要更长的时间.如果您在类中四处移动代码而未更改其行为,则无需更新其测试.测试应该告诉您一切仍然有效!

  • 有意义的代码覆盖范围

如果您为每种受保护的方法编写测试,则会从代码覆盖率报告中删除一个继承的好处:它不会告诉您不再调用哪些受保护的函数.这是(恕我直言)不好的事情,因为您要么没有正确地测试所有公共方法(为什么在测试每种情况下为什么都没有调用一个方法?),要么您真的不需要该方法,但由于它是绿色",因此您无需再三思.

引用PHPUnit作者

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

http://sebastian-bergmann.de/archives/881- Testing-Your-Privates.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天全站免登陆