如何对 symfony/console 应用程序命令进行单元测试?

问题描述 投票:0回答:1

我仅使用 symfony/console 库来创建一个小型 cli 应用程序。

我想按原样对命令进行单元测试,但单元测试没有提供输出。

这是我的单元测试设置:

class TimrOverviewCommandTest extends TestCase
{
    public function testTimrOverviewCommand()
    {
        $input = new ArgvInput(argv: [
            "overview",
            "--csv",
            "tests/csv/day_report.csv"
        ]);

        $buffered = new BufferedOutput();

        $app = new Timr(__DIR__);
        $exitCode = $app->run($input, $buffered);
        $result = $buffered->fetch();

        $this::assertSame(actual: $result, expected: "2024-10-18: Expected 5 / Delivered 5.25\n");
    }
}

这就是我的应用程序的设置方式:

class Timr
{
    private readonly Application $app;

    public function __construct(string $rootDir)
    {
        $parser = new CsvParser($rootDir);

        $app = new Application('timr', '1.0.0');

        $app->add(new TimrReportCommand($parser));
        $app->add(new TimrOverviewCommand($parser));

        $this->app = $app;
    }

    public function run(?InputInterface $input = null, ?OutputInterface $output = null): int
    {
        return $this->app->run($input, $output);
    }
}

有几个相关的问题,但其中大多数似乎都在整个 symfony Web 应用程序的范围内和/或已经过时了:

php unit-testing symfony phpunit symfony-console
1个回答
0
投票

有两个陷阱:


argv
又名
tokens
数组的第一项将在
ArgvInput
构造函数中删除:

$argv ??= $_SERVER['argv'] ?? [];

// strip the application name
array_shift($argv);

$this->tokens = $argv;

解决方案:将另一个项目添加到您的argv数组中:

    $input = new ArgvInput(argv: [
        "name", // will be stripped
        "overview",
        "--csv",
        "tests/csv/day_report.csv"
    ]);

另一个问题是应用程序在任务完成后完全关闭的默认行为。这是通过

autoexit
标志处理的:

App::run

if ($this->autoExit) {
    if ($exitCode > 255) {
        $exitCode = 255;
    }

    exit($exitCode);
}

return $exitCode;

解决方案:禁用应用程序定义中的标志。

$app = new Application('timr', '1.0.0');
$app->setAutoExit(false);
© www.soinside.com 2019 - 2024. All rights reserved.