如何对 PHP 特征进行单元测试
How to unit test PHP traits
我想知道是否有关于如何对 PHP 特征进行单元测试的解决方案。
我知道我们可以测试一个使用该特征的 class,但我想知道是否有更好的方法。
提前感谢您的任何建议:)
编辑
一种替代方法是在测试中使用 Trait class 本身,正如我将在下面演示的那样。
但是 我不太喜欢这种方法,因为不能保证特征、class 和 PHPUnit_Framework_TestCase
(在这个例子中):
这是一个特征示例:
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;
}
}
及其测试:
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');
}
}
您可以使用类似于测试抽象 Class' 具体方法的方法来测试特征。
PHPUnit has a method getMockForTrait 这将 return 一个使用特征的对象。然后就可以测试traits函数了
这是文档中的示例:
<?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());
}
}
?>
您也可以使用 getObjectForTrait
,然后根据需要断言实际结果。
class YourTraitTest extends TestCase
{
public function testGetQueueConfigFactoryWillCreateConfig()
{
$obj = $this->getObjectForTrait(YourTrait::class);
$config = $obj->getQueueConfigFactory();
$this->assertInstanceOf(QueueConfigFactory::class, $config);
}
public function testGetQueueServiceWithoutInstanceWillCreateConfig()
{
$obj = $this->getObjectForTrait(YourTrait::class);
$service = $obj->getQueueService();
$this->assertInstanceOf(QueueService::class, $service);
}
}
自 PHP 7 我们现在可以使用匿名 类...
$class = new class {
use TheTraitToTest;
};
// We now have everything available to test using $class
我想知道是否有关于如何对 PHP 特征进行单元测试的解决方案。
我知道我们可以测试一个使用该特征的 class,但我想知道是否有更好的方法。
提前感谢您的任何建议:)
编辑
一种替代方法是在测试中使用 Trait class 本身,正如我将在下面演示的那样。
但是 我不太喜欢这种方法,因为不能保证特征、class 和 PHPUnit_Framework_TestCase
(在这个例子中):
这是一个特征示例:
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;
}
}
及其测试:
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');
}
}
您可以使用类似于测试抽象 Class' 具体方法的方法来测试特征。
PHPUnit has a method getMockForTrait 这将 return 一个使用特征的对象。然后就可以测试traits函数了
这是文档中的示例:
<?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());
}
}
?>
您也可以使用 getObjectForTrait
,然后根据需要断言实际结果。
class YourTraitTest extends TestCase
{
public function testGetQueueConfigFactoryWillCreateConfig()
{
$obj = $this->getObjectForTrait(YourTrait::class);
$config = $obj->getQueueConfigFactory();
$this->assertInstanceOf(QueueConfigFactory::class, $config);
}
public function testGetQueueServiceWithoutInstanceWillCreateConfig()
{
$obj = $this->getObjectForTrait(YourTrait::class);
$service = $obj->getQueueService();
$this->assertInstanceOf(QueueService::class, $service);
}
}
自 PHP 7 我们现在可以使用匿名 类...
$class = new class {
use TheTraitToTest;
};
// We now have everything available to test using $class