Laravel容器不解决测试方法依赖性

时间:2016-01-29 10:27:33

标签: php laravel laravel-5 phpunit inversion-of-control

我在App\Commands命名空间中创建了 CLI 程序的测试套件。我遇到的问题是,laravel容器似乎无法解决测试方法依赖关系,也无法解决laravel帮助程序.......我在 Windows 10

PHP代码:

<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

use ACME\SomeClass;

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
    }

}

我创造了&amp;包括服务提供商:

<?php

use ACME\SomeClass;

$this->app->bind('ACME\SomeClass', function($app){
    return new SomeClass($value);
});

当我从phpunitPATH运行vendor/bin时出现此错误:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACME\SomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 and defined in C:\path\tests\CLICommandTest.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:\path\tests\CLICommandTest.php on line 16

Fatal error: Uncaught TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACME\SomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 and defined in C:\path\tests\CLICommandTest.php on line 16

TypeError: Argument 1 passed to CLICommandTest::__construct() must be an instance of ACME\SomeClass, none given, called in phar://C:/PHPUnit/phpunit/phpunit/Framework/TestSuite.php on line 475 in C:\path\tests\CLICommandTest.php on line 16

Call Stack:
    0.0036     492584   1. {main}() C:\PHPUnit\phpunit:0
    0.1375    8875000   2. PHPUnit_TextUI_Command::main() C:\PHPUnit\phpunit: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

问题是什么?

2 个答案:

答案 0 :(得分:1)

在类的use块名称中应该匹配:

<?php

use ACME\SomeClass; // <== see, it should be SomeClass here, not someClass

$this->app->bind('ACME\SomeClass', 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 testingPHPUnit docs以了解如何编写测试以及为什么很少需要扩展构造函数。

看起来你也想使用setUp/tearDown方法:

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';
    }
    ...

答案 1 :(得分:0)

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

虽然您仍然可以使用辅助函数来利用容器:

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

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