Traits are a mechanism for reusing code in language with inheritance such as PHP. A trait attempts to reduce some limitations of simple inheritance by allowing the developer to reuse a number of methods in independent classes. They also reduce the complexity and problems associated with multiple inheritance.
I have already been confronted with a unit test of a trait declaring a constructor with dependencies. The solutions a had implemented did not work because there was a bug in PHPUnit 6.5.14 that I was using. Then I created a bug in PHPUnit (see link https://github.com/sebastianbergmann/phpunit/issues/3722). Thanks to Sebastian Bergmann for fixing the bug. The solution will be available in PHPUnit 8.2.3
Class to test
Here is an example of trait to test:
<?php
namespace AppBundle\Traits;
use AppBundle\Service\myClass;
/**
* trait MyTrait
*/
trait MyTrait
{
/**
* @var MyClass
*/
private $myClass;
/**
* MyTrait constructor.
*
* @param MyClass $myClass
*/
public function __construct(MyClass $myClass)
{
$this->myClass = $myClass;
}
/**
* @return string
*/
public function method(): string
{
return $this->myClass->myMethod();
}
}
The dependency class:
<?php
namespace AppBundle\Service;
/**
* Class MyClass
*/
class MyClass
{
/**
* @return string
*/
public function myMethod(): string
{
return 'Hello word !';
}
}
Unit test
The unit test is:
<?php
namespace Tests\AppBundle\Traits;
use AppBundle\Traits\MyTrait;
use AppBundle\Service\MyClass;
use PHPUnit\Framework\TestCase;
class TestMyTraitTest extends TestCase
{
/**
* Test method
*/
public function testMethod()
{
$myClass = $this->createMock(MyClass::class);
$myClass->expects($this->once())
->method('myMethod')
->willReturn('some-string');
$myTrait = $this->getObjectForTrait(MyTrait::class, [$myClass]);
$this->assertSame('some-string', $myTrait->method());
}
}