使用Mockey测试交互式工匠命令

时间:2019-03-18 11:59:15

标签: laravel unit-testing artisan mockery

guide之后,我正在Laravel 5.3中编写交互式命令的单元测试,但似乎无法使Mockery正常工作。

我已经建立了一个简单的命令greet:user

public function handle()
{
    if(!$name = $this->argument('name')) {
        $name = $this->ask('Name of user to greet');
    }

    $this->info("Hello {$name}.");
}

然后像这样写unit-tests

public function testCanGreetGivenUser()
{
    $command = Mockery::mock('App\Console\Commands\GreetUser[info]');

    $command->shouldReceive('info')->once()->with('Hello Brian.');

    $exit_code = Artisan::call('greet:user', ['name' => 'Brian', '--no-interaction' => true]);
    $this->assertEquals(trim(Artisan::output()), 'Hello Brian.');
    $this->assertEquals($exit_code, 0);
}

问题:

Mockery\Exception\InvalidCountException: Method info("Hello Brian.") from Mockery_0_App_Console_Commands_GreetUser should be called exactly 1 times but called 0 times.

我的目标是测试;

如果没有输入内容

$this->artisan('greet:user', ['name' => 'Brian'])
    ->expectsOutput('Hello Brian.')
    ->assertExitCode(0);

如果需要输入。

$this->artisan('greet:user')
    ->expectsQuestion('Name of user to greet', 'James')
    ->expectsOutput('Hello James.')
    ->assertExitCode(0);

这就是我在Laravel 5.7中可以做到的方式,但是如何在Laravel 5.3中实现相同的效果

1 个答案:

答案 0 :(得分:0)

要解决该问题,您必须按以下方式调用测试:

public function testCanGreetGivenUser()
{
    $command = Mockery::mock('\App\Console\Commands\GreetUser[info]');

    $command->shouldReceive('info')->once()->with('Hello Brian.');

    $this->app[\Illuminate\Contracts\Console\Kernel::class]->registerCommand($command);

    $exit_code = $this->artisan('greet:user', ['name' => 'Brian', '--no-interaction' => true]);
    $this->assertEquals($exit_code, 0);
}

决定因素是命令注册。您必须执行此操作才能用您的模拟实际替换命令的现有实例。