Laravel 测试 | Laravel Artisan 命令中的模拟对象

Posted

技术标签:

【中文标题】Laravel 测试 | Laravel Artisan 命令中的模拟对象【英文标题】:Laravel Test | Mock object in Laravel Artisan Command 【发布时间】:2019-11-13 03:34:30 【问题描述】:

我想测试我的 Laravel Artisan 命令。所以我需要模拟一个对象并存根这个模拟的对象方法。在我的测试中,我无法使用真正的 SFTP 环境。

这是我的命令的handle()

public function handle()

   $sftp = new SFTP('my.sftpenv.com');
   $sftp->login('foo', 'bar');

我想在我的测试中模拟 SFTP:

$sftp = $this->createMock(SFTP::class);
$sftp->expects($this->any())->method('login')->with('foo', 'bar');
$this->artisan('import:foo');

Cannot connect to ...:22 中运行测试结果,它来自SFTP 的原始login 方法。所以mock/stub没有生效。

所以我的问题是:如何在 Laravel Artisan 命令测试中模拟对象?

【问题讨论】:

您可以在容器中注入模拟对象。在此行之前:$this->artisan('import:foo'); 你能举个例子吗? 顺便说一句:$this->app->bind(SFTP::class, $sftp); 【参考方案1】:

我认为@Mesuti 的意思是,如果您将bind 您的SFTP 对象添加到您的服务容器中,您将能够在运行测试时将其替换为模拟对象。

您可以像这样绑定它(在您的 app/Providers/AppServiceProvider.php 或新的服务提供者中):

$this->app->singleton(SFTP::class, function ($app) 
            return new SFTP('my.sftpenv.com');
        );

然后您可以在命令的处理程序中 resolve 对象(例如 $sftp = resolve('SFTP');),然后在您的测试中使用 mock 它,如下所示:

$this->mock(SFTP::class, function ($mock) 
    $mock->expects()->login('foo', 'bar')->andReturn('whatever you want it to return');
);

请注意,您正在模拟的服务应该在命令的handle 方法中解决,而不是像您在其他情况下经常做的那样在__construct 方法中解决。似乎工匠命令在测试运行之前已解决,因此如果您在命令的构造函数中解析服务,它不会解析为模拟实例。

【讨论】:

以上是关于Laravel 测试 | Laravel Artisan 命令中的模拟对象的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 从 5.5 升级到 5.6 到 5.7:未捕获 ReferenceError: axios is not defined

Laravel 测试 | Laravel Artisan 命令中的模拟对象

测试一个 Laravel 包

测试 laravel 路由识别方法类型

Laravel 5 如何测试重定向

使用 laravel 黄昏测试数据库