【问题标题】:PHPUnit ensuring a trait satisfies an interfacePHPUnit 确保 trait 满足接口
【发布时间】:2017-12-13 13:44:25
【问题描述】:

我们看一下psr/log中的代码,特别是:

众所周知,trait 不能实现接口,所以这两个部分需要一个类才能成功连接在一起。

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

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

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 的功能

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

【问题讨论】:

  • 你为什么在乎?类实现接口比实现接口的方式更重要。
  • 这里的重点不是class,而是trait。确实,我不在乎课程。

标签: php testing interface phpunit traits


【解决方案1】:

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

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

【讨论】:

  • 这是可能的。
  • 逐字创建模拟对象的好答案和建议。恕我直言,不需要断言。如果接口不能(完全)满足,PHP 将在对象创建时给出致命错误,请参阅3v4l.org/gAlRI - 如果 PHPUnit 捕获此(可捕获错误)或以 255 退出代码退出(防止进一步测试) - 我想这取决于使用的 PHP 版本。在任何情况下都不会调用断言。所以测试更多的是安全检查(甚至可能根本没有必要,但这是主观的,因为我不能代表 OP)。
  • @hakre 该断言很有用,因为它明确了我们关心的内容。如果我们对不断言任何内容的测试进行严格配置,这也很有用(请参阅phpunit.de/manual/current/en/risky-tests.html)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-08
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
  • 2017-05-17
相关资源
最近更新 更多