PHP symfony4:KernelTestCase中的命令

时间:2018-04-19 11:49:19

标签: php dependency-injection phpunit symfony4

您好我正在尝试为symfony4控制台命令创建单元测试,但我无法正确注入依赖项。我对symfony4很新,所以也许这对你们来说是个基本问题。

我的单元测试如下:

<?php

namespace App\Tests\Command;

use App\Command\ExecuteSalesTaskCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;
use Psr\Log\LoggerInterface;
use App\Repository\TaskRepository;

class ExeculteSalesTaskCommandTest extends KernelTestCase
{
    /**
     * @param LoggerInterface $logger
     * @param TaskRepository  $taskRepository
     */
    public function testExecute(LoggerInterface $logger, TaskRepository $taskRepository)
    {
        $kernel      = self::bootKernel();
        $application = new Application($kernel);

        $application->add(new ExecuteSalesTaskCommand($logger,$taskRepository));

        # UPDATED
        $logger         = self::$kernel->getContainer()->get(LoggerInterface::class);
        $taskRepository = self::$kernel->getContainer()->get(TaskRepository::class);

        $command       = $application->find('app:execute-sales-task');
        $commandTester = new CommandTester($command);
        $commandTester->execute(
            [
                'command'  => $command->getName(),
            ]
        );

        // the output of the command in the console
        $output = $commandTester->getDisplay();
        $this->assertContains('Execute sales resulted: ', $output);
    }
}

我的问题是我得到了这样的注射错误:

  

ArgumentCountError:函数参数太少   App \ Tests \ Command \ ExeculteSalesTaskCommandTest :: testExecute(),0   通过,正好2预期

更新: 当我从容器中取出依赖项时,我遇到了这种错误:

  

有1个错误:

     

1)App \ Tests \ Command \ ExeculteSalesTaskCommandTest :: testExecute   Symfony的\分量\ DependencyInjection \异常\ ServiceNotFoundException的:   “Psr \ Log \ LoggerInterface”服务或别名已被删除或   在编译容器时内联。你应该做到   public,或者直接停止使用容器并使用依赖项   注入而不是。

如何正确注入必要的依赖项,以便创建ExecuteSalesTaskCommand的实例?

2 个答案:

答案 0 :(得分:1)

我也遇到类似的问题。但是跟随对我有用。我认为您不需要向应用程序添加命令并再次找到它?请找到以下解决方案。它可能会帮助别人。

<?php
// BaseCommandTester.php
/**
 * This is basis for the writing tests, that will cover commands
 *
 */
namespace App\Tests\Base;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Dotenv\Dotenv;

class BaseCommandTester extends KernelTestCase
{
    /**
     * @var
     */
    private $application;

    /**
     * to set test environment and initiate application kernel
     */
    public function setUp()
    {
        /**
         * get test env
         */
        $dotenv = new Dotenv();
        $dotenv->load('/var/www/.env.test');

        /**
         * boot kernel
         */
        $kernel = self::bootKernel();
        $this->application = new Application($kernel);
        parent::setUp();
    }

    /**
     * @return mixed
     */
    public function getApplication()
    {
        return $this->application;
    }

    /**
     * @param mixed $application
     */
    public function setApplication($application)
    {
        $this->application = $application;
    }

}

测试用例

// FeedUpdaterCommandTest.php
<?php

namespace App\Tests\Command;

use App\Tests\Base\BaseCommandTester;
use Symfony\Component\Console\Tester\CommandTester;

class FeedUpdaterCommandTest extends BaseCommandTester
{
    /**
     * test to update all feeds
     */
    public function testExecuteUpdateAll() {
        /**
         * init command tester and executre
         */
        $commandName = 'app:feedUpdater';
        $expectedResult = '[OK] Update Success Feed Type : All';

        $command = $this->getApplication()->find($commandName);
        $commandTester = new CommandTester($command);
        $commandTester->execute(array(
            'command' => $command->getName()
        ));

        /**
         * get result and compare output
         */
        $result = trim($commandTester->getDisplay());
        $this->assertEquals($result, $expectedResult);
    }
}

试运行结果

#Run tests
root@xxx:/var/www# bin/phpunit tests/Command
#!/usr/bin/env php
PHPUnit 6.5.13 by Sebastian Bergmann and contributors.

Testing tests/Command
2018-11-28T07:47:39+00:00 [alert] Successful update of popularProducts Feeds!
2018-11-28T07:47:39+00:00 [alert] Successful update of topVouchers Feeds!
.                                                                   1 / 1 (100%)

Time: 1.44 seconds, Memory: 12.00MB

OK (1 test, 1 assertion)

我正在使用以下Sf4版本

 -------------------- --------------------------------------
  Symfony
 -------------------- --------------------------------------
  Version              4.1.7

服务定义及其默认为私有

#config/services.yml
    App\Service\FeedGenerator:
        arguments:
            $feeds: '%feed_generator%'

我认为您无需再次自动接线。

答案 1 :(得分:0)

我发现问题是我尝试手动加载依赖项。使用自动装配,如下所示:

public function testExecute()
{
    $dotenv = new Dotenv();
    $dotenv->load(__DIR__.'/.env.test');

    $kernel      = self::bootKernel();
    $application = new Application($kernel);

    $executeSalesCommand = self::$kernel->getContainer()->get(
        'console.command.public_alias.App\Command\ExecuteSalesTaskCommand'
    );

    $application->add($executeSalesCommand);

    $command       = $application->find('app:execute-sales-task');
    $commandTester = new CommandTester($command);
    $commandTester->execute(
        [
            'command' => $command->getName(),
        ]
    );

    // the output of the command in the console
    $output = $commandTester->getDisplay();

    // do your asserting stuff
}

您需要从内核容器中获取命令。现在它有效。