PHPUnit确保特性满足接口

PHPUnit确保特性满足接口,php,testing,interface,phpunit,traits,Php,Testing,Interface,Phpunit,Traits,让我们看一下中的代码,特别是: 正如您所知,trait无法实现接口,因此这两个部分需要一个类才能成功地连接在一起 假设我介绍了特性的测试(通过PHPUnit的getMockForTrait相对容易)。接下来要测试的是,我想证明特质满足接口 就代码而言,它看起来非常简单: public function testThatTraitSatisfiesInterface() { $className = 'test_class_' . uniqid(); $classCode

让我们看一下中的代码,特别是:

正如您所知,trait无法实现接口,因此这两个部分需要一个类才能成功地连接在一起

假设我介绍了特性的测试(通过PHPUnit的
getMockForTrait
相对容易)。接下来要测试的是,我想证明特质满足接口

就代码而言,它看起来非常简单:

public function testThatTraitSatisfiesInterface()
{
    $className = 'test_class_' . uniqid();
    $classCode = sprintf(
        'class %s implements %s { use %s; }',
        $className,
        LoggerAwareInterface::class,
        LoggerAwareTrait::class
    );

    eval($classCode); // ewww :see_no_evil:
    new $className(); // no errors? good, test successful
}
A在这里有几个问题:

  • 我希望尽可能避免使用
    eval()
    (即使我知道这是PHPUnit的驱动力),但是
  • 如果可能的话,我宁愿使用PHPUnit的功能

因此,最大的问题是,有其他选择吗?

创建类作为测试资产怎么样:

namespace Foo\Bar\Test\Asset;

use Psr\Log;

final class LoggerAware implements Log\LoggerAwareInterface
{
    use Log\LoggerAwareTrait;
}
然后断言它实现接口:

namespace Foo\Bar\Test;

use PhpUnit\Framework;
use Psr\Log;

final class LoggerAwareTest extends Framework\TestCase
{
    public function testImplementsLoggerAwareInterface()
    {
        $loggerAware = new Asset\LoggerAware();

        $this->assertInstanceOf(Log\LoggerAwareInterface::class, $loggerAware);
    }
}

你为什么在乎?类实现接口比它如何实现接口更重要。这里的重点不是类,而是特性。事实上,我并不关心这个类。这是一种可能性。很好的答案和建议是逐字创建模拟对象。IMHO不需要该断言。如果接口不能(完全)满足要求,PHP将在对象创建时给出一个致命错误,请参阅-不能从我的头脑中说出PHPUnit是否捕获到这个错误(可捕获错误)或使用255个退出代码退出(阻止进一步测试)-我想这取决于使用的PHP版本。在任何情况下都不会调用断言。因此,测试更像是一种安全检查(甚至可能根本没有必要,但这是主观的,因为我不能代表OP说话)。@hakre这个断言很有用,因为它明确了我们关心的问题。如果我们对不断言任何内容的测试进行严格配置,那么这也很有用(请参阅)。