LoginSignup
3
1

More than 5 years have passed since last update.

Command::ask()など、コンソールからの入力を受け付けるartisanコマンドのテスト

Posted at

問題点

何らかの入力を求めるartisnaコマンドをphpunitでテストしようとした場合、ただartisanコマンドを実行するだけではいつまでも入力待ちの状態になりテストが行うことが出来ない。

Commandクラス

本当は入力値を使用してDBに書き込み・・・などすると思うが、ここでは必要最低限のコードのみを記載する。

TestCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class TestCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test_command';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $name = $this->ask('名前は?');
        $this->info("あなたの名前は{$name}です。");
    }
}

Kernelクラス

Kernel.php
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        \App\Console\Commands\TestCommand::class
    ];

通常のartisanコマンド実行

artisan
$ php artisan --ansi test_command

 名前は?:
 > 山田太郎

あなたの名前は山田太郎です。

上記artisanコマンドを実行するようなテストクラス

入力待ちのまま固まってしまいプロセスを強制終了するしかない。

CommandTest
class CommandTest extends TestCase
{
    /**
     * @see \MasterDataSeeder
     */
    public function test001()
    {
//        $this->artisan('test_command');
    }
}

回避方法

こちらを参考にさせてもらいました。

上記artisanコマンドを実行するようなテストクラス

ask()をモック化して、常に山田太郎を返却するようにしています。
もしパスワードの入力などを求めていてsecret()を使用している場合も同様に対応可能です。

CommandTest
class CommandTest extends TestCase
{
    /**
     * @see \MasterDataSeeder
     */
    public function test001()
    {
        $command = \Mockery::mock("\App\Console\Commands\TestCommand[ask]");
        $command->shouldReceive('ask')->once()->andReturn('山田太郎');
        $command->setLaravel($this->app->make('Illuminate\Contracts\Foundation\Application'));
        $command->setApplication($this->app->make('Symfony\Component\Console\Application'));

        $tester = new CommandTester($command);
        $tester->execute([]);
        $this->assertSame("あなたの名前は山田太郎です。" . PHP_EOL, $tester->getDisplay());
    }
}
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1