在测试 artisan 控制台命令时调用整数上的成员函数 expectsOutput()

Call to a member function expectsOutput() on integer when testing artisan console command

我有一个非常简单的例子来说明问题:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class VendorCounts extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'vendor:counts
                            {year : The year of vendor counts}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Runs vendor counts';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->info('Starting Vendor Counts');
    }
}
<?php

namespace Tests\Feature\Console\Vendor;

use Tests\TestCase;

class VendorCountsTest extends TestCase {

    public function testVendorCounts()
    {
        $this->artisan('vendor:counts', ['year' => 2019])
             ->expectsOutput('Starting Vendor Counts')
             ->assertExitCode(0);
    }
}

我收到以下错误:

1) Tests\Feature\Console\Vendor\VendorCountsTest::testVendorCounts
Error: Call to a member function expectsOutput() on integer

/Users/albertski/Sites/vrs/tests/Feature/Console/Vendor/VendorCountsTest.php:12

我知道命令肯定会运行,因为如果我在其中放入转储语句,它会显示调试输出。

我正在使用 Laravel 6.3。是否有不同的测试方法?

你能把这个添加到你的 VendorCountsTest class:

public $mockConsoleOutput = true;

这是由特征设置的,但只是确保某些东西没有改变值。当 $mockConsoleOutputfalse 时,它会直接 运行 artisan 命令。当它是 true 时,它将把它包装在一个 PendingCommand 对象中,该对象具有您要调用的那些方法。

我使用的问题是 TestCaseLaravel\BrowserKitTesting\TestCase 用作 BaseTestCase。我最终为控制台命令创建了另一个 Base。

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class ConsoleTestCase extends BaseTestCase
{
    use CreatesApplication;
}

我有一个问题,在我的 Artisan class 上使用 expectedOutput() 会一直失败,原来是因为我使用了 exit() and/or die() 在一个方法中,它确实不能很好地与 phpunit 测试方法一起使用。

所以如果你想在某个时候停止处理“脚本”,只要使用一个空的 return 而不是 exit()die() 如果你想利用内置的 -在 ->artisan() 测试 Laravel.

工作示例:

<?php
// app/Console/Commands/FooCommand.php
public function handle()
{
  $file = $this->argument('file');
  
  if (! file_exists($file)) {
    $this->line('Error! File does not exist!');
    return;
  }
}

// tests/Feature/FooCommandTest.php
public function testFoo() {
  $this->artisan('foo', ['file' => 'foo.txt'])->expectsOutput('Something');
}

非工作示例:

<?php
// app/Console/Commands/FooCommand.php
public function handle()
{
  $file = $this->argument('file');
  
  if (! file_exists($file)) {
    $this->line('Error! File does not exist!');
    exit;
  }
}

// tests/Feature/FooCommandTest.php
public function testFoo() {
  $this->artisan('foo', ['file' => 'foo.txt'])->expectsOutput('Something');
}