模拟 Laravel 命令依赖项

Dim*_*las 1 php phpunit command laravel laravel-5.7

正如 Laravel 官方文档所述,我执行了以下命令:

namespace App\Console\Commands;

use App\Model\Report;
use Illuminate\Console\Command;
use Exception;

class ExportAnualReport extends Command
{
    /**
     * @var string
     */
    protected $description = "Print Anual Report";

    /**
     * @var string
     */
    protected $signature = "report:anual";

    public function __construct()
    {
        parent::__construct();
    }

    public function handle(Report $report): int
    {
        //@todo Implement Upload
        try {
            $reportData = $report->getAnualReport();
            $this->table($reportData['headers'], $reportData['data']);
            return 0;
        } catch (Exception $e) {
            $this->error($e->getMessage());
            return 1;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但我已经遵循了 Laravel 的方法和建议,而不是这个问题中使用的方法 ,并且利用依赖注入来将我的模型作为服务插入。

所以我同时认为对它进行单元测试是一个好主意:

namespace Tests\Command;

use App\Model\Report;
use Tests\TestCase;

class TripAdvisorUploadFeedCommandTest extends TestCase
{
    public function setUp()
    {
        parent::setUp();
    }

    public function testFailAnualReport()
    {
        $this->artisan('report:anual')->assertExitCode(1);
    }

    public function testSucessAnualReport()
    {
        $this->artisan('report:anual')->assertExitCode(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

但就我而言,我已经Report通过函数将雄辩模型注入到我的命令中handle,所以我想Report模拟对象实例而不是访问实际的数据库。

作为记录,Report对象如下:

namespace App\Model

use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon
use Illuminate\Database\Eloquent\ModelNotFoundException;

class Report extends Model
{
     /**
     * @var string
     */
    protected $table = 'myapp_report_records';

    /**
     * @var string
     */
    protected $primaryKey = 'report_id';

    public function getAnualReport()
    {
        $now=Carbon::now();
        $oneYearBefore=new Carbon($now);
        $oneYearBefore->modify('-1 year');

        $results=$this->where('date','>',$oneYearBefore)->where('date','<',$now)->all();

        if(empty($results)){
            throw new ModelNotFoundException();
        }

        return $results;
    }
}
Run Code Online (Sandbox Code Playgroud)

那么我如何模拟提供的Report模型呢?

小智 5

首先,您需要创建模型报告类的模拟,然后需要将其绑定到容器。这样,每当您在命令类中调用报告模型类时,您都会有一个模拟模型类,其中包含您期望的特定响应。

$this->app->instance(Report::class, \Mockery::mock(Report::class, function($mock){
            $mock->shouldReceive('getAnualReport')->andReturn(['headers'=>'any values', 'data'=>'any values']);
        }));
Run Code Online (Sandbox Code Playgroud)