
Laravel测试Artisan命令需用expectsQuestion预设交互输入,严格匹配提示字符串(含空格标点),并按顺序链式调用;输出断言用getDisplay()获取带ANSI码的原始内容,配合strip_tags()或正则清理后验证;assertExitCode(0)失效常因未捕获异常、手动exit或构造函数报错导致命令未执行到结尾。
expectsQuestion 模拟用户输入Artisan 命令里用了 $this->ask()、$this->confirm() 等交互方法时,直接跑测试会卡住。Laravel 提供了 expectsQuestion 来预设回答,但要注意它只匹配「完全一致的提示字符串」——包括空格和标点。
expectsQuestion 必须在 artisan() 调用前链式调用,顺序错就无效$this->ask('Name? ', 'default'),测试中必须写 expectsQuestion('Name? ', 'alice'),末尾空格不能少$this->confirm('Continue?'),传 true 或 false 即可,但字符串提示仍要一字不差expectsQuestion,不能跳过中间某一个public function test_it_prompts_for_name_and_email()
{
$this->artisan('make:user')
->expectsQuestion('Name? ', 'Taylor')
->expectsQuestion('Email? ', 'taylor@laravel.com')
->assertExitCode(0);
}
光看退出码不够,常需验证是否打印了预期文本。Laravel 的 artisan() 测试方法默认不返回输出,得用 run() + getDisplay() 手动抓取。
assertSee(),那是 HTTP 测试用的;Artisan 命令测试里得靠 getDisplay()
getDisplay() 返回带 ANSI 转义符的原始输出,含颜色控制符(如 \x1B[32m),断言前建议用 strip_tags() 或正则清理assertStringContainsString(
) 或正则匹配关键静态部分getErrorOutput(),比如 php artisan invalid:command 的报错信息$output = $this->artisan('list')->run();
$this->assertStringContainsString('make:user', $output->getDisplay());
assertExitCode(0) 有时不生效assertExitCode() 看似简单,但实际失败往往不是逻辑错,而是命令提前异常终止或没真正执行到结尾。
assertExitCode
exit() 或 die() —— Artisan 命令严禁手动 exit,应改用 return self::FAILURE
handle() 外部(比如构造函数)抛异常,命令甚至不会进入执行流程,assertExitCode 不会被触发exec('php artisan ...') 这种绕过框架的方式会让所有内置断言失效单测某个环节容易漏掉组合问题。比如用户输错格式后命令打印错误提示并退出 1,这种场景必须三者联动验证。
expectsQuestion 给非法输入(如邮箱不带 @)getDisplay() 确认错误文案出现assertExitCode(1) 确保没静默成功$this->error() 输出,它也出现在 getDisplay() 里,不是 getErrorOutput()
最易忽略的是 ANSI 颜色字符干扰断言,以及提示字符串里隐藏的不可见空格 —— 这类细节不打日志根本看不出哪里不匹配。