使用 Mockery 测试 Laravel Command 尝试
使用 Mockery 测试 Laravel Command 尝试
概述
由于 Laravel 官方支持的 Artisan 命令行测试原理为实际调用一次命令,再校验其输出。故如果仅测试 Command 类中的一个方法时就会无从下手。而 Command 的实例化也很复杂,源码看的头晕。关键的获取命令行输入始终无法模拟,所以想着能否借用 Mockery 工具模拟一个 Input 类,达到模拟输入的目的。
示例
现有 Command 代码如下。
<?php
...
use Illuminate\Console\Command;
class SampleCommand extends Command
{
...
public function initMode()
{
return $this->option('init-mode');
}
...
已知 \Illuminate\Console\Command::option($key) 方法是通过调用 \Symfony\Component\Console\Input\InputInterface::getOption($name) 实现的。
/**
* Get the value of a command option.
*
* @param string|null $key
* @return string|array|bool|null
*/
public function option($key = null)
{
if (is_null($key)) {
return $this->input->getOptions();
}
return $this->input->getOption($key);
}
而 \Illuminate\Console\Command::$input 属性可以通过 \Illuminate\Console\Command::setInput($input) 方法注入。
那么,可以通过 Mockery 模拟一个 \Symfony\Component\Console\Input\InputInterface 接口的实现,来替换原有的 $input 。
测试代码如下。
<?php
use Mockery;
use Tests\TestCase;
class SampleCommandTest extends TestCase
{
public function testInitMode()
{
$command = $this->app->get(SampleCommand::class);
$input = Mockery::mock(\Symfony\Component\Console\Input\InputInterface::class);
$input->shouldReceive('getOption')->with('init-mode')->andReturn(false);
$command->setInput($input);
$this->assertFalse($commond->initMode());
}
}
这样就能通过模拟一个 Input 来测试 Laravel Command 的一个获取输入选项值的方法了。
总结
虽然这个例子看起来没什么卵用,但是仔细思考一下的话,就能发现这套做法还是很有用的。
浙公网安备 33010602011771号