How do I test the concrete methods of an abstract class with PHPUnit?
I'd expect that I'd have to create some sort of object as part of the test. Though, I've no idea the best practice for this or if PHPUnit allows for this.
How do I test the concrete methods of an abstract class with PHPUnit?
I'd expect that I'd have to create some sort of object as part of the test. Though, I've no idea the best practice for this or if PHPUnit allows for this.
Unit testing of abstract classes doesn't necessary mean testing the interface, as abstract classes can have concrete methods, and this concrete methods can be tested.
It is not so uncommon, when writing some library code, to have certain base class that you expect to extend in your application layer. And if you want to make sure that library code is tested, you need means to UT the concrete methods of abstract classes.
Personally, I use PHPUnit, and it has so called stubs and mock objects to help you testing this kind of things.
Straight from PHPUnit manual:
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());
}
}
Mock object give you several things:
That's a good question. I've been looking for this too.
Luckily, PHPUnit already has getMockForAbstractClass() method for this case, e.g.
protected function setUp()
{
$stub = $this->getMockForAbstractClass('Some_Abstract_Class');
$this->_object = $stub;
}
Note that this requires PHPUnit > 3.5.4. There was a bug in previous versions.
To upgrade to the newest version:
sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit
Eran, your method should work, but it goes against the tendency of writing the test before the actual code.
What I would suggest is to write your tests on the desired functionality of a non-abstract subclass of the abstract class in question, then write both the abstract class and the implementing subclass, and finally run the test.
Your tests should obviously test the defined methods of the abstract class, but always via the subclass.
If you do not want to subclass the abstract class just to perform a unit test on the methods which are implemented in the abstract class already, you could try to see whether your framework allows you to mock abstract classes.