Laravel 5.6测试问题:get()方法持久化查询字符串异常
解决Laravel 5.6测试中get()方法持久化查询字符串的问题
我在Laravel 5.6做测试的时候也踩过这个坑——测试客户端会复用请求实例,导致前一次请求的查询字符串会“粘”在下一次请求上,完全打乱测试预期。结合你的测试代码场景,给你几个靠谱的解决办法:
首先先还原下你可能遇到的完整测试场景(方便对应问题):
/** * @test */ public function returns_records_filtered_by_search() { factory(NewsletterSubscriber::class)->states('verified')->create([ 'email' => 'jon@doe.com', 'first_name' => 'Jon', 'last_name' => 'Doe', ]); factory(NewsletterSubscriber::class)->states('verified')->create([ 'email' => 'jane@doe.com', 'first_name' => 'Jane', 'last_name' => 'Doe', ]); // 第一次带搜索参数请求,预期返回1条结果 $response = $this->get('/subscribers?search=Jon'); $response->assertJsonCount(1); // 第二次不带参数请求,预期返回2条结果,但实际还是带着search=Jon的参数,导致断言失败 $response = $this->get('/subscribers'); $response->assertJsonCount(2); }
问题根源
Laravel 5.6的测试HTTP客户端会复用底层的Request实例,所以前一次请求的查询参数会被保留到下一次请求中,造成了“持久化”的假象。
解决方案
方案1:用call()方法替代get(),明确控制查询参数
call()方法的参数设计更直观,直接把查询参数作为第三个参数传递,完全不会有参数残留的问题,这也是我最推荐的方式:
// 带搜索参数的请求 $response = $this->call('GET', '/subscribers', ['search' => 'Jon']); $response->assertJsonCount(1); // 不带参数的请求,直接传空数组 $response = $this->call('GET', '/subscribers', []); $response->assertJsonCount(2);
方案2:重置请求的查询参数
如果不想改太多现有代码,可以在两次请求之间手动清空查询参数:
$response = $this->get('/subscribers?search=Jon'); $response->assertJsonCount(1); // 清空查询参数 $this->app['request']->query->clear(); $response = $this->get('/subscribers'); $response->assertJsonCount(2);
方案3:在get请求中明确覆盖查询字符串
通过get()方法的第三个参数(server数组),手动设置QUERY_STRING来覆盖之前的参数:
$response = $this->get('/subscribers', [], ['QUERY_STRING' => 'search=Jon']); $response->assertJsonCount(1); // 第二次请求设置空的查询字符串 $response = $this->get('/subscribers', [], ['QUERY_STRING' => '']); $response->assertJsonCount(2);
这三个方案里,方案1的代码可读性最高,也最不容易出问题,建议优先用这个。
内容的提问来源于stack exchange,提问作者Sebastian Sulinski
相关产品推荐
相关产品推荐

