Laravel Feature Tests中Request::path()始终返回/如何解决?
问题根因
你遇到的Request::path()始终返回/的核心原因是路由注册时机和请求处理时机的错位:
Laravel的路由是在应用启动阶段(接收请求之前)就完成注册的,你在路由定义中直接写Route::any(Request::path(), 'ExternalController@handle'),这段代码里的Request::path()会在路由文件被加载的时候就执行,此时还没有收到你的测试请求,拿到的自然是默认的根路径/。无论后续测试时发送什么路径的请求,路由规则已经被提前注册为external前缀下匹配根路径的规则,自然不会生效。你这套写法在生产环境如果开启了路由缓存,同样会完全失效。
正确解决方案
不要在路由定义中动态读取当前请求路径,Laravel本身提供了捕获前缀下所有路径的标准写法:
Route::prefix('external')->group(function () { // {all} 匹配任意长度的路径片段,where条件限定all可以包含斜杠 Route::any('{all}', 'ExternalController@handle')->where('all', '.*'); });
改完之后你原来的测试用例不需要做任何修改,就能正常匹配到/api/external/*下的所有请求,也不需要手动模拟$_SERVER或者Mock Request对象。
之前尝试的方案失效原因
- 用
withServerVariables传入参数:这个方法设置的是测试请求的服务变量,但此时路由早已完成注册,修改请求参数不会改变已经注册好的路由规则 - 直接Mock Request的path方法:首先Mock的时机晚于路由注册,路由加载时调用的
Request::path()没有被Mock到;其次直接Mock整个Request门面会破坏Laravel内置的请求处理流程,框架内部需要调用Request的其他方法(比如setUserResolver),你只声明了path方法的预期,其他方法调用就会报错,补充再多预期也很容易遗漏框架内部的调用逻辑,完全不推荐这种实现方式。
内容的提问来源于stack exchange,提问作者suben
相关产品推荐
相关产品推荐

