英文:
Symfony testing my command demands passing parameter to constructor. Why?
问题
Symfony 6
Doctrine 3
phpunit
我的原始命令正在正常运行。没有什么特别的。现在我想编写一个测试用例。但我得到的只有:
运行:php bin/phpunit tests/Command/IsbnCleanupCommandTest.php
发生了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
<?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: 'Add a short description for your command',
)]
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, 'Argument description')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$arg1 = $input->getArgument('arg1');
// set state value to NULL (=reset)
$this->isbnRepository->resetStateValues();
/* … flawless code … */
$io->success('You have a new command! Now make it your own! Pass --help to see your options.');
return Command::SUCCESS;
}
}
My test
<?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([
// pass arguments to the helper
// 'username' => 'John',
// ...
]);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('...', $output);
// or use the tester to assert on the exit code
// $this->assertSame(0, $commandTester->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.
<?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->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);
// ...
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论