Symfony控制器调用自定义命令时单元测试未执行问题求助
问题描述
通过Symfony控制器调用自定义命令时,命令立即返回[OK] success,但实际并未执行单元测试。该命令在CLI中运行正常,单元测试本身也能正常执行,且无任何报错信息。
控制器代码
<?php namespace App\Controller\Api; use OpenApi\Annotations as OA; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Process\Process; use Symfony\Component\Routing\Annotation\Route; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; class UnitTestController extends AbstractController { private $kernel; public function __construct(KernelInterface $kernel) { $this->kernel = $kernel; } #[Route('/unit_tests', name: 'unit_test', methods: 'GET')] public function unitTest(): Response { $application = new Application($this->kernel); $application->setAutoExit(false); $input = new ArrayInput([ 'command' => 'mapi:unitTests', ]); $output = new BufferedOutput(); $application->run($input, $output); $content = $output->fetch(); dd($content); } }
自定义命令代码
<?php namespace App\Command; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Process\Process; use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface; use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface; use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface; #[AsCommand( name: 'mapi:unitTests', description: 'lancement des tests unitaires', )] class unitTestCommand extends Command { /** * @param InputInterface $input * @param OutputInterface $output * @return int * @throws ClientExceptionInterface * @throws DecodingExceptionInterface * @throws RedirectionExceptionInterface * @throws ServerExceptionInterface */ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); ini_set('max_execution_time', 300); $process = Process::fromShellCommandline('php vendor/bin/phpunit'); $process->run(); $io->success('success'); return Command::SUCCESS; } }
解决方案
1. 修正工作目录
Web服务器的工作目录通常不是项目根目录,导致找不到phpunit脚本。需要指定Process的工作目录为Symfony项目根目录:
// 在命令类中获取项目目录参数 $projectDir = $this->getContainer()->getParameter('kernel.project_dir'); $process = Process::fromShellCommandline('php vendor/bin/phpunit', $projectDir);
2. 添加执行状态检查
当前代码未验证phpunit是否成功执行,直接返回success。添加错误处理逻辑:
$process->run(); // 检查进程执行状态 if (!$process->isSuccessful()) { $io->error('单元测试执行失败:' . $process->getErrorOutput()); return Command::FAILURE; } // 输出phpunit的执行结果到命令行输出 $io->write($process->getOutput()); $io->success('success');
3. 检查Web服务器权限
确保运行Web服务器的用户(如www-data)拥有项目目录的读写权限,特别是vendor目录和测试文件所在目录。可以通过以下命令调整权限(根据实际情况修改):
chown -R www-data:www-data /path/to/your/project chmod -R 755 /path/to/your/project
4. 指定PHP绝对路径
Web环境中php命令的路径可能与CLI环境不同,使用绝对路径指定PHP二进制文件:
// 替换为服务器上实际的PHP路径,比如/usr/bin/php $process = Process::fromShellCommandline('/usr/bin/php vendor/bin/phpunit', $projectDir);
内容的提问来源于stack exchange,提问作者lataix.sebastien
相关产品推荐
相关产品推荐

