拉拉维尔测试 | 在拉拉维尔工匠命令中使用模拟对象

5

我希望测试我的 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方法。因此,模拟/存根没有生效。
我的问题是:在Laravel Artisan命令测试中,我该如何模拟一个对象?

1
你可以将模拟对象注入到容器中。在这行代码之前:$this->artisan('import:foo'); - Mesuti
你能提供一个例子吗? - schellingerht
1
顺便说一下,它可以这样做:$this->app->bind(SFTP::class, $sftp); - Mesuti
1个回答

3
我认为@Mesuti的意思是,如果你将SFTP对象与服务容器绑定,则在运行测试时可以将其替换为模拟对象。
你可以像这样绑定它(在app/Providers/AppServiceProvider.php内或一个新的服务提供者内):
$this->app->singleton(SFTP::class, function ($app) {
            return new SFTP('my.sftpenv.com');
        });

您可以在命令处理程序中解析该对象(例如:$sftp = resolve('SFTP');),然后在测试中模拟它,如下所示:

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

对于未来的读者,需要注意的是,您正在嘲笑的服务应该在命令的handle方法中解决,而不是像您通常在其他情况下所做的那样在__construct方法中解决。似乎artisan命令在测试运行之前被解决,因此如果您在命令的构造函数中解决服务,则不会解决为模拟实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接