PHPUnit确保特性满足接口

问题描述:

Let's look at the code in psr/log, in particular:

As you know, a trait cannot implement an interface, so these two parts need a class to be successfully connected together.

Let's say I cover testing of the trait (it's relatively easy via PHPUnit's getMockForTrait). The next thing to test is that I want to prove that the trait satisfies the interface.

In terms of code, it looks simple enough:

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 have a few concerns here:

  • I'd like to avoid eval() as much as possible (even if I know that it's what drives PHPUnit anyway), but..
  • I'd rather use PHPUnit's functionality if at all possible

So the big question is, are there any alternatives?

让我们看一下 psr / log code> ,特别是: p>

  • LoggerAwareTrait code> a > li>
  • LoggerAwareInterface code> li> ul>

    如您所知,特征无法实现接口,因此这两个部分需要一个类才能成功连接在一起 。 p>

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

    在代码方面,它看起来很简单: p>

      public function testThatTraitSatisfiesInterface()
     {
     $ className ='test_class_'。  uniqid(); 
     $ classCode = sprintf(
    '类%s实现%s {使用%s;}',
     $ className,
     LoggerAwareInterface :: class,
     LoggerAwareTrait :: class 
    );  
     
     eval($ classCode);  // ewww:see_no_evil:
     new $ className();  //没有错误? 好,测试成功
    } 
      code>  pre> 
     
     

    这里有一些问题: p>

    • 我是 喜欢尽可能避免 eval() code>(即使我知道它是驱动PHPUnit的原因),但是.. li>
    • 我宁愿使用PHPUnit的功能,如果 在可能的情况下 li> ul>

      所以最大的问题是,还有其他选择吗? p> div>

How about just creating the class as a test asset:

namespace Foo\Bar\Test\Asset;

use Psr\Log;

final class LoggerAware implements Log\LoggerAwareInterface
{
    use Log\LoggerAwareTrait;
}

And then asserting it implements the interface:

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);
    }
}