You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.4中如何测试含ask()方法的Artisan命令

解决Laravel Artisan命令ask()方法Mock测试卡顿问题

看起来你遇到的核心问题是手动创建的Mock实例没被Artisan工具使用,再加上Mockery的调用设置有误,导致测试时实际跑了真实的命令,卡在等待用户输入的环节。我帮你一步步修正:

1. 先修正Mockery的ask()模拟逻辑

你原来的链式写法有问题,连续调用shouldReceive('ask')会覆盖之前的设置。得针对每个提问(或者按调用顺序)指定返回值,两种写法都可以:

方式一:匹配具体提问内容(更严谨)

$command = Mockery::mock('\App\Console\Commands\Questions');
// 针对每个问题分别设置返回值
$command->shouldReceive('ask')
    ->with('Ask question 1')
    ->andReturn('Answer 1')
    ->shouldReceive('ask')
    ->with('Ask question 2')
    ->andReturn('Answer 2')
    ->shouldReceive('ask')
    ->with('Ask question 3')
    ->andReturn('Answer 3');

方式二:按调用次数批量返回(更简洁)

如果不需要匹配具体提问文本,只需要按顺序返回答案:

$command->shouldReceive('ask')
    ->times(3) // 指定调用3次
    ->andReturn('Answer 1', 'Answer 2', 'Answer 3'); // 按顺序返回对应值

2. 让Artisan使用你的Mock实例

光创建Mock没用,得把它绑定到Laravel的容器里,这样$this->artisan()调用时才会用你的Mock,而不是实例化真实的命令类:

$this->app->instance(\App\Console\Commands\Questions::class, $command);

完整的测试代码示例

public function testCommandSavesToDatabase()
{
    // 创建命令的Mock实例
    $command = Mockery::mock('\App\Console\Commands\Questions');
    
    // 模拟三次ask调用的返回值
    $command->shouldReceive('ask')
        ->with('Ask question 1')
        ->andReturn('Answer 1')
        ->shouldReceive('ask')
        ->with('Ask question 2')
        ->andReturn('Answer 2')
        ->shouldReceive('ask')
        ->with('Ask question 3')
        ->andReturn('Answer 3');
    
    // 将Mock绑定到容器,替换真实的命令类
    $this->app->instance(\App\Console\Commands\Questions::class, $command);
    
    // 运行Artisan命令
    $this->artisan('myCommand:toRun');
    
    // 验证数据库是否正确保存数据
    $this->assertDatabaseHas('myTable', [
        'question1' => 'Answer 1', // 注意这里要和你实际保存的字段值对应,原代码里的'answer1'是变量名,不是值
        'question2' => 'Answer 2',
        'question3' => 'Answer 3',
    ]);
}

额外注意事项

  • 确保你的命令类的$signature属性确实是myCommand:toRun,否则$this->artisan()找不到对应的命令。
  • 测试类记得在tearDown()方法里加上Mockery::close();,避免Mockery残留影响其他测试。
  • 原测试里的assertDatabaseHas参数要和你实际存入数据库的字段、值对应,别把变量名(比如answer1)当成字段值用。

内容的提问来源于stack exchange,提问作者Linas Lg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:38:39