Symfony测试我的命令需要将参数传递给构造函数。为什么?

huangapple go评论62阅读模式
英文:

Symfony testing my command demands passing parameter to constructor. Why?

问题

Symfony 6
Doctrine 3
phpunit

我的原始命令正在正常运行。没有什么特别的。现在我想编写一个测试用例。但我得到的只有:

运行:php bin/phpunit tests/Command/IsbnCleanupCommandTest.php

发生了1个错误:

  1. App\Tests\Command\IsbnCleanupCommandTest::testExecute
    ArgumentCountError: 传递给函数的参数太少
    App\Command\IsbnCleanupCommand::__construct(),期望传递0个参数,
    在/var/www/company/tests/Command/IsbnCleanupCommandTest.php的第18行传递了3个参数

为什么在测试时我需要传递参数给构造函数?如果我运行命令,就不需要传递参数。

我的命令

<?php

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\TitelmetaRepository;
use App\Repository\IsbnRepository;

#[AsCommand(
    name: 'IsbnCleanup',
    description: '为您的命令添加简短描述',
)]
class IsbnCleanupCommand extends Command
{

    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager, TitelMetaRepository $titelMetaRepository, IsbnRepository $isbnRepository)
    {
        parent::__construct();
        $this->entityManager = $entityManager;
        $this->titelMetaRepository = $titelMetaRepository;
        $this->isbnRepository = $isbnRepository;
    }    

    protected function configure(): void
    {
        $this
            ->addArgument('arg1', InputArgument::OPTIONAL, '参数描述')
            ->addOption('option1', null, InputOption::VALUE_NONE, '选项描述')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $arg1 = $input->getArgument('arg1');
        
        // 设置状态值为NULL(重置)
        
        $this->isbnRepository->resetStateValues();

        /* … 无误的代码 … */

        $io->success('您有一个新命令!现在将其改为您自己的命令。使用--help查看选项。');

        return Command::SUCCESS;
    }
}

我的测试

<?php

namespace App\Tests\Command;

use App\Command\IsbnCleanupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;

class IsbnCleanupCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = static::createKernel();
        $kernel->boot();

        $application = new Application($kernel);
        $application->add(new IsbnCleanupCommand());

        $command = $application->find('app:IsbnCleanup');
        $commandTester = new CommandTester($command);
        $commandTester->execute([
            // 传递参数给助手
            // 'username' => 'John',
            // ...
        ]);

        // 控制台中命令的输出
        $output = $commandTester->getDisplay();
        $this->assertStringContainsString('...', $output);

        // 或者使用测试器来断言退出码
        // $this->assertSame(0, $commandTester->getStatusCode());
    }
}
英文:

Symfony 6
Doctrine 3
phpunit

My origin command is running as it should. Nothing special about it. Now I wanted to write a test case. But all I get is:

Running: php bin/phpunit tests/Command/IsbnCleanupCommandTest.php

> There was 1 error:
>
> 1) App\Tests\Command\IsbnCleanupCommandTest::testExecute
> ArgumentCountError: Too few arguments to function
> App\Command\IsbnCleanupCommand::__construct(), 0 passed in
> /var/www/company/tests/Command/IsbnCleanupCommandTest.php on line 18
> and exactly 3 expected

Why do I have to pass parameters to the constructor when testing? If I run the command, I don't have to.

My command

&lt;?php

namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\TitelmetaRepository;
use App\Repository\IsbnRepository;

#[AsCommand(
    name: &#39;IsbnCleanup&#39;,
    description: &#39;Add a short description for your command&#39;,
)]
class IsbnCleanupCommand extends Command
{

    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager, TitelMetaRepository $titelMetaRepository, IsbnRepository $isbnRepository)
    {
        parent::__construct();
        $this-&gt;entityManager = $entityManager;
        $this-&gt;titelMetaRepository = $titelMetaRepository;
        $this-&gt;isbnRepository = $isbnRepository;
    }    

    protected function configure(): void
    {
        $this
            -&gt;addArgument(&#39;arg1&#39;, InputArgument::OPTIONAL, &#39;Argument description&#39;)
            -&gt;addOption(&#39;option1&#39;, null, InputOption::VALUE_NONE, &#39;Option description&#39;)
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $arg1 = $input-&gt;getArgument(&#39;arg1&#39;);
        
        // set state value to NULL (=reset)
        
        $this-&gt;isbnRepository-&gt;resetStateValues();

/* … flawless code  … */

        $io-&gt;success(&#39;You have a new command! Now make it your own! Pass --help to see your options.&#39;);

        return Command::SUCCESS;
    }
}

My test

&lt;?php

namespace App\Tests\Command;

use App\Command\IsbnCleanupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;

class IsbnCleanupCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = static::createKernel();
        $kernel-&gt;boot();

        $application = new Application($kernel);
        $application-&gt;add(new IsbnCleanupCommand());

        $command = $application-&gt;find(&#39;app:IsbnCleanup&#39;);
        $commandTester = new CommandTester($command);
        $commandTester-&gt;execute([
            // pass arguments to the helper
            // &#39;username&#39; =&gt; &#39;John&#39;,
            // ...
        ]);

        // the output of the command in the console
        $output = $commandTester-&gt;getDisplay();
        $this-&gt;assertStringContainsString(&#39;...&#39;, $output);

        // or use the tester to assert on the exit code
        // $this-&gt;assertSame(0, $commandTester-&gt;getStatusCode());
    }
}

答案1

得分: 1

根据您的要求,这是您提供的代码片段的翻译部分:

根据这里的描述,我在更改了我的代码后成功运行了测试,构造函数也不再出现问题。


// tests/Command/CreateUserCommandTest.php
namespace App\Tests\Command;

use App\Command\IsbnCleanupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;

class IsbnCleanupCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = self::bootKernel();
        $application = new Application($kernel);

        $command = $application->find('IsbnCleanup');
        $commandTester = new CommandTester($command);
        $commandTester->execute([
            // pass arguments to the helper
            // 'username' => 'Wouter',

            // prefix the key with two dashes when passing options,
            // e.g: '--some-option' => 'option_value',
            // use brackets for testing array value,
            // e.g: '--some-option' => ['option_value'],
        ]);

        $commandTester->assertCommandIsSuccessful();

        // the output of the command in the console
        $output = $commandTester->getDisplay();
        $this->assertStringContainsString('Username: Wouter', $output);

        // ...
    }
}

英文:

As described here I was able to run the test after changing my code there was no hustle with the constructor anymore.

&lt;?php

// tests/Command/CreateUserCommandTest.php
namespace App\Tests\Command;

use App\Command\IsbnCleanupCommand;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;

class IsbnCleanupCommandTest extends KernelTestCase
{
    public function testExecute()
    {
        $kernel = self::bootKernel();
        $application = new Application($kernel);

        $command = $application-&gt;find(&#39;IsbnCleanup&#39;);
        $commandTester = new CommandTester($command);
        $commandTester-&gt;execute([
            // pass arguments to the helper
            //&#39;username&#39; =&gt; &#39;Wouter&#39;,

            // prefix the key with two dashes when passing options,
            // e.g: &#39;--some-option&#39; =&gt; &#39;option_value&#39;,
            // use brackets for testing array value,
            // e.g: &#39;--some-option&#39; =&gt; [&#39;option_value&#39;],
        ]);

        $commandTester-&gt;assertCommandIsSuccessful();

        // the output of the command in the console
        $output = $commandTester-&gt;getDisplay();
        $this-&gt;assertStringContainsString(&#39;Username: Wouter&#39;, $output);

        // ...
    }
}

huangapple
  • 本文由 发表于 2023年5月17日 22:13:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273070.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定