假设我具有当前具有方法的特征:
trait MyTrait
{
public function traitMethod()
{
return true;
}
}
现在让我们说这个特征已被多个类使用,但我不想为每个类编写一个单元测试。 相反,我只想为特征编写一个单元测试:
public function testTraitMethod()
{
$trait = $this->getMockForTrait(MyTrait::class);
$this->assertTrue($trait->traitMethod());
}
但是问题是,一个类实际上可能覆盖特质的方法:
class MyClass
{
use MyTrait;
public function traitMethod()
{
return false;
}
}
在这种情况下,MyClass
做错了事,但由于仅测试特征,所以我不知道。
我的想法是为每个类编写一个单元测试,只是为了检查它是否正在使用该特性并且没有覆盖该方法。如果一个类需要重写trait的方法,那么它也需要一个特定的单元测试。
目前,我正在为实现我的特质的每个类编写单元测试,但是当然到处都是复制粘贴测试。
那么有没有一种方法可以测试一个类是否调用了它的基础特征方法?
答案 0 :(得分:0)
我找到了使用Reflection
的解决方案,我将其发布,以防万一有人需要它,因为我找不到与问题相关的任何东西。随意发表评论或添加其他解决方案。
因此,以下测试断言$serviceClass
使用$traitClass
,并且不覆盖$traitClass
中声明的方法,除了抽象方法和那些手动添加到$overriddenMethods
数组中的方法。
public function testServiceUsesTrait()
{
$serviceClass = MyClass::class;
$traitClass = MyTrait::class;
$this->assertContains($traitClass, (new \ReflectionClass($serviceClass))->getTraitNames());
$reflectedTrait = new \ReflectionClass($traitClass);
$reflectedTraitFile = $reflectedTrait->getFileName();
/**
* If $serviceClass overrides some trait methods they
* should be inserted into this array to avoid test failure.
* Additional unit-tests should be written for overridden methods.
*/
$overriddenMethods = [];
foreach ($reflectedTrait->getMethods() as $traitMethod) {
if ($traitMethod->isAbstract() || in_array($traitMethod->getName(), $overriddenMethods, true)) {
continue;
}
$classMethod = new \ReflectionMethod($serviceClass, $traitMethod->getName());
$this->assertSame($reflectedTraitFile, $classMethod->getFileName(), sprintf(
'Trait method "%s" is overridden in class "%s" thus it must be excluded from this test.',
$traitMethod->getName(), $serviceClass
));
}
}
我还尝试了使用$classMethod->getDeclaringClass()
而不是文件名来比较声明类,但是它没有用:即使trait方法没有在类中被覆盖,getDeclaringClass()
总是返回类本身。