传递给 Foo::__construct() 的参数 1 必须是 Psr\Log\LoggerTrait 的实例,给定的 Mock_Trait_LoggerTrait_65811a25_bdddd884 实例

Argument 1 passed to Foo::__construct() must be an instance of Psr\Log\LoggerTrait, instance of Mock_Trait_LoggerTrait_65811a25_bdddd884 given

我正在尝试使用 PHPUnit 模拟一个简单的特征,但它会导致 FatalError,如果我删除类型提示,它会起作用:传递给 Foo::__construct() 的参数 1 必须是 Psr\Log\LoggerTrait,Mock_Trait_LoggerTrait_65811a25_bdddd884 的实例给定

class:

use Psr\Log\LoggerTrait;

class Foo {

    /**
     * @var LoggerTrait
    */
    private $mLogger;

    public function __construct(LoggerTrait $iLogger)
    {
        $this->mLogger = $iLogger;
    }
}

测试:

class FooTest extends \PHPUnit_Framework_TestCase
{
    public function testRun ()
    {
        $logger = $this->getMockForTrait('\Psr\Log\LoggerTrait');

        $sut = new Foo($logger);
    }
}

我该如何解决?

您不能键入提示特征。您的类型提示正在寻找 \Psr\Log\LoggerTrait 类型的 class。看起来它实际上是一个特征而不是一个对象。

http://php.net/manual/en/language.oop5.typehinting.php

getMockForTrait 方法用于创建特征的具体对象,以便您可以测试特征功能。它创建一个对象,该对象使用 traits 方法和任何被模拟的抽象方法。它不扩展特征,因此类型提示无效。

https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mocking-traits-and-abstract-classes

你似乎在滥用你想要做的事情的特征。特征是 PHP 允许 classes 共享功能而无需相互扩展的方式。特征无法实例化,它们将用于在其他不相关的对象之间共享功能。

您的 "trait" 应该只是您传入的 class。然后您的测试将变为:

public function testRun ()
{
    $logger = $this->getMock('\Psr\Log\Logger');  //Changed name to not be Trait

    $sut = new Foo($logger);
}