如何使用PHPUnit测试抽象类的具体方法?
我希望我必须创建某种对象作为测试的一部分.虽然,我不知道最好的做法,或者如果PHPUnit允许这样做.
抽象类的单元测试不一定意味着测试接口,因为抽象类可以有具体的方法,并且可以测试这些具体的方法.
在编写一些库代码时,为了拥有您希望在应用程序层中扩展的某个基类,这种情况并不少见.如果你想确保库代码经过测试,你需要手段来表示抽象类的具体方法.
就个人而言,我使用PHPUnit,它有所谓的存根和模拟对象来帮助您测试这类事情.
直接来自PHPUnit手册:
abstract class AbstractClass { public function concreteMethod() { return $this->abstractMethod(); } public abstract function abstractMethod(); } class AbstractClassTest extends PHPUnit_Framework_TestCase { public function testConcreteMethod() { $stub = $this->getMockForAbstractClass('AbstractClass'); $stub->expects($this->any()) ->method('abstractMethod') ->will($this->returnValue(TRUE)); $this->assertTrue($stub->concreteMethod()); } }
模拟对象给你几件事:
你不需要具有抽象类的具体实现,而是可以使用stub来逃避
你可以调用具体方法并断言它们正确执行
如果具体方法依赖于未实现的(抽象)方法,则可以使用will()PHPUnit方法存根返回值
这是个好问题.我一直在寻找这个.
幸运的是,PHPUnit已经有了getMockForAbstractClass()
这种情况的方法,例如
protected function setUp() { $stub = $this->getMockForAbstractClass('Some_Abstract_Class'); $this->_object = $stub; }
请注意,这需要PHPUnit> 3.5.4.以前的版本中有一个错误.
要升级到最新版本:
sudo pear channel-update pear.phpunit.de sudo pear upgrade phpunit/PHPUnit
应该注意的是,从PHP 7 开始,添加了对匿名类的支持.这为您为抽象类设置测试提供了额外的途径,该抽象类不依赖于PHPUnit特定的功能.
class AbstractClassTest extends \PHPUnit_Framework_TestCase { /** * @var AbstractClass */ private $testedClass; public function setUp() { $this->testedClass = new class extends AbstractClass { protected function abstractMethod() { // Put a barebones implementation here } }; } // Put your tests here }