I want to know if there is a solution on how to unit-test a PHP trait.
I know we can test a class which is using the trait, but I was wondering if there are better approaches.
Thanks for any advice in advance :)
EDIT
One alternative is to use the Trait in the test class itself as I'm going to demonstrate bellow.
But I'm not that keen on this approach since there is no guaranty there are no similar method names between the trait, the class and also the PHPUnit_Framework_TestCase
(in this example):
Here is an example trait:
trait IndexableTrait { /** @var int */ private $index; /** * @param $index * @return $this * @throw \InvalidArgumentException */ public function setIndex($index) { if (false === filter_var($index, FILTER_VALIDATE_INT)) { throw new \InvalidArgumentException('$index must be integer.'); } $this->index = $index; return $this; } /** * @return int|null */ public function getIndex() { return $this->index; } }
and its test:
class TheAboveTraitTest extends \PHPUnit_Framework_TestCase { use TheAboveTrait; public function test_indexSetterAndGetter() { $this->setIndex(123); $this->assertEquals(123, $this->getIndex()); } public function test_indexIntValidation() { $this->setExpectedException(\Exception::class, '$index must be integer.'); $this->setIndex('bad index'); } }
PHPUnit is a unit testing framework for the PHP programming language. It is an instance of the xUnit design for unit testing systems that began with SUnit and became popular with JUnit. Even a small software development project usually takes hours of hard work.
In the PHP Explorer, right-click the file, and select New | PHPUnit Test Case. The New PHPUnit Test Case dialog is displayed. To select the element to be tested, click Browse next to the Tested Element field. The Element selection dialog is displayed.
The simplest way is to mock the parent class and then do your unit tests on the trait. Or you can make a specific class to implement the trait, solely for unit testing, but that assumes your trait doesn't do anything that interacts with the parent or vice versa.
Traits can have properties and methods with private and protected visibility too. You can access them like they belong to class itself. There is no difference.
You can test a Trait using a similar to testing an Abstract Class' concrete methods.
PHPUnit has a method getMockForTrait which will return an object that uses the trait. Then you can test the traits functions.
Here is the example from the documentation:
<?php trait AbstractTrait { public function concreteMethod() { return $this->abstractMethod(); } public abstract function abstractMethod(); } class TraitClassTest extends PHPUnit_Framework_TestCase { public function testConcreteMethod() { $mock = $this->getMockForTrait('AbstractTrait'); $mock->expects($this->any()) ->method('abstractMethod') ->will($this->returnValue(TRUE)); $this->assertTrue($mock->concreteMethod()); } } ?>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With