Laravel容器不解析测试方法依赖项



我有一个测试服,用于在命名空间中创建AppCommands CLI 程序。我遇到的问题是,似乎 laravel 容器无法解决测试方法依赖项或 laravel 助手,... .我使用的是 Windows 10

PHP代码:

<?php
use IlluminateFoundationTestingWithoutMiddleware;
use IlluminateFoundationTestingDatabaseMigrations;
use IlluminateFoundationTestingDatabaseTransactions;
use ACMESomeClass;
class CLICommandTest extends TestCase
{
    use DatabaseTransactions;
    protected $key = '';
    protected $someClass = null;
    public function __construct(SomeClass $someClass)
    {
        parent::__construct();
        $this->someClass = $someClass;
        $this->key = config('someconfig')['key'];
    }
    /*
     * test handle method
     */
    public function testHandle()
    {
        //assertions
    }
}

我已经为此创建并包含服务提供商:

<?php
use ACMESomeClass;
$this->app->bind('ACMESomeClass', function($app){
    return new SomeClass($value);
});

当我从PATHvendor/bin运行phpunit时,会出现此错误:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACMESomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 and defined in C:pathtestsCLICommandTest.php:16
Stack trace:
#0 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php(475): CLICommandTest->__construct()
#1 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php(880): PHPUnit_Framework_TestSuite::createTest(Object(ReflectionClass), 'testHandle')
#2 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php(195): PHPUnit_Framework_TestSuite->addTestMethod(Object(ReflectionClass), Object(ReflectionMethod))
#3 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php(297): PHPUnit_Framework_TestSuite->__construct(Object(ReflectionClass))
#4 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php(381): PHPUnit_Framework_TestSuite->addTestSuite(Object(ReflectionClass))
#5 phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuit in C:pathtestsCLICommandTest.php on line 16
Fatal error: Uncaught TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACMESomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 and defined in C:pathtestsCLICommandTest.php on line 16
TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACMESomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 in C:pathtestsCLICommandTest.php on line 16
Call Stack:
    0.0036     492584   1. {main}() C:PHPUnitphpunit:0
    0.1375    8875000   2. PHPUnit_TextUI_Command::main() C:PHPUnitphpunit:515
    0.1375    8878160   3. PHPUnit_TextUI_Command->run() phar://C:/PHPUnit/phpunit/phpunit/TextUI/Command.php:106
    0.1375    8878160   4. PHPUnit_TextUI_Command->handleArguments() phar://C:/PHPUnit/phpunit/phpunit/TextUI/Command.php:117
    0.1624   10379328   5. PHPUnit_Util_Configuration->getTestSuiteConfiguration() phar://C:/PHPUnit/phpunit/phpunit/TextUI/Command.php:663
    0.1624   10379912   6. PHPUnit_Util_Configuration->getTestSuite() phar://C:/PHPUnit/phpunit/phpunit/Util/Configuration.php:796
    0.1651   10381496   7. PHPUnit_Framework_TestSuite->addTestFiles() phar://C:/PHPUnit/phpunit/phpunit/Util/Configuration.php:885
    0.1651   10381496   8. PHPUnit_Framework_TestSuite->addTestFile() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:409
    0.1732   10916648   9. PHPUnit_Framework_TestSuite->addTestSuite() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:381
    0.1732   10917104  10. PHPUnit_Framework_TestSuite->__construct() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:297
    0.1733   10982344  11. PHPUnit_Framework_TestSuite->addTestMethod() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:195
    0.1733   10982760  12. PHPUnit_Framework_TestSuite::createTest() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:880
    0.1735   10986272  13. CLICommandTest->__construct() phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php:475

问题出在哪里?

use中,类的块名应匹配:

<?php
use ACMESomeClass; // <== see, it should be SomeClass here, not someClass
$this->app->bind('ACMESomeClass', function($app){
    return new SomeClass($value); 
});

除此之外,您的class CLICommandTest extends TestCase实际上扩展了\PHPUnit_Framework_TestCase。它的构造函数签名是:

public function __construct($name = null, array $data = [], $dataName = '')

其中第一个参数是测试的名称,它是可选的。你

public function __construct(SomeClass $someClass)

用更严格的要求覆盖签名:第一个参数是必需的,并且必须具有类型 SomeClass 。它会制动合约,因此测试运行程序无法实例化测试用例。

我建议阅读Laravel测试和PHPUnit文档,了解如何编写测试以及为什么很少需要扩展构造函数。

看起来你也想使用设置/拆卸方法:

class CLICommandTest extends TestCase
{
    use DatabaseTransactions; // <== please double check you need the trait here
    protected $key = '';
    protected $someClass = null;
    public function setUp()
    {
        // here you probably want to create an instance of your application 
        $this->someClass = new SomeClass;
        $this->key = 'value of the key';
    }
    ...

Laravel和phpunit是独立的框架。只有在 laravel 应用程序的某些部分(控制器、事件等)中,您才能传入类依赖项,服务容器将解析它们。phpunit与此无关。

尽管您仍然可以使用帮助程序函数来利用容器:

$someObject = app()->make(SomeClass::class);

但是,对于测试,您可能希望模拟对象而不是从头开始构建它,在这种情况下,请使用 Mockery 库。

最新更新