首页 文章

Laravel 5控制台(工匠)命令单元测试

提问于
浏览
12

我正在将我的Laravel 4.2应用程序迁移到5.1(从5.0开始),并且我的控制台命令单元测试很麻烦 . 我有工匠命令,我需要测试生成的控制台输出,正确的问题/响应处理以及与其他服务的交互(使用模拟) . 尽管如此,Laravel文档在测试控制台命令方面仍然是无声的 .

我终于找到了一种创建这些测试的方法,但感觉就像是那些 setLaravelsetApplication 调用的黑客 .

有一个更好的方法吗?我希望我可以将我的模拟实例添加到Laravel IoC容器中,并让它创建命令以测试所有正确设置的内容 . 我担心我的单元测试会在较新的Laravel版本中轻松破解 .

这是我的单元测试:

使用陈述:

use Mockery as m;
use App\Console\Commands\AddClientCommand;
use Symfony\Component\Console\Tester\CommandTester;

Build

public function setUp() {
    parent::setUp();

    $this->store = m::mock('App\Services\Store');

    $this->command = new AddClientCommand($this->store);

    // Taken from laravel/framework artisan command unit tests
    // (e.g. tests/Database/DatabaseMigrationRollbackCommandTest.php)
    $this->command->setLaravel($this->app->make('Illuminate\Contracts\Foundation\Application'));

    // Required to provide input to command questions (provides command->getHelper())
    // Taken from ??? when I first built my command tests in Laravel 4.2
    $this->command->setApplication($this->app->make('Symfony\Component\Console\Application'));
}

输入作为命令参数提供 . 检查控制台输出

public function testReadCommandOutput() {
    $commandTester = new CommandTester($this->command);

    $result = $commandTester->execute([
        '--client-name' => 'New Client',
    ]);

    $this->assertSame(0, $result);
    $templatePath = $this->testTemplate;

    // Check console output
    $this->assertEquals(1, preg_match('/^Client \'New Client\' was added./m', $commandTester->getDisplay()));
}

由模拟键盘键提供的输入

public function testAnswerQuestions() {
    $commandTester = new CommandTester($this->command);

    // Simulate keyboard input in console for new client
    $inputs = $this->command->getHelper('question');
    $inputs->setInputStream($this->getInputStream("New Client\n"));
    $result = $commandTester->execute([]);

    $this->assertSame(0, $result);
    $templatePath = $this->testTemplate;

    // Check console output
    $this->assertEquals(1, preg_match('/^Client \'New Client\' was added./m', $commandTester->getDisplay()));
}

protected function getInputStream($input) {
    $stream = fopen('php://memory', 'r+', false);
    fputs($stream, $input);
    rewind($stream);
    return $stream;
}

更新

  • 这在Laravel 5.1中不起作用#11946

1 回答

  • 8

    我之前做过如下操作 - 我的控制台命令返回一个json响应:

    public function getConsoleResponse()
    {
        $kernel = $this->app->make(Illuminate\Contracts\Console\Kernel::class);
        $status = $kernel->handle(
            $input = new Symfony\Component\Console\Input\ArrayInput([
                'command' => 'test:command', // put your command name here
            ]),
            $output = new Symfony\Component\Console\Output\BufferedOutput
        );
    
        return json_decode($output->fetch(), true);
    }
    

    所以如果你想把它放在它自己的命令测试器类中,或者作为TestCase中的一个函数等等......由你决定 .

相关问题