求助:Laravel+Cartalyst环境下首次测试无扩展路由问题
我之前维护Laravel+Cartalyst项目时刚好碰到过一模一样的问题,核心原因就是首次测试运行时,Cartalyst Platform的路由还没被正确注册,而后续测试因为Laravel测试框架默认复用了应用实例,之前加载过的路由就保留下来了。你打印的路由数量差异也完全能佐证这点:11条是Laravel自带的基础路由,329条才是包含Cartalyst所有业务路由的完整集合。
Cartalyst Platform 7.0的路由一般是通过延迟加载的服务提供者来注册的,首次测试启动时,这些服务提供者还没被触发(比如没有访问到对应路由或者调用到相关服务),所以路由池里只有Laravel的基础路由,自然会返回404。
下面几个方法按优先级推荐,你可以挨个试试:
1. 手动触发Cartalyst路由加载(最优解)
在你的测试类的setUp方法里,手动调用Cartalyst路由服务提供者的启动逻辑,强制加载所有路由。比如:
use Illuminate\Foundation\Testing\TestCase as BaseTestCase; class YourTestCase extends BaseTestCase { protected function setUp(): void { parent::setUp(); // 手动启动Cartalyst的路由服务提供者 $this->app->make(\Cartalyst\Platform\Providers\RoutingServiceProvider::class)->boot(); // 如果上面的方法不行,试试调用Platform facade的路由加载方法(Cartalyst 7.0可能有这个方法) // \Cartalyst\Platform\Facades\Platform::loadRoutes(); } }
这个方法不会影响测试速度,只是在每次测试前确保路由都加载完成。
2. 重写createApplication方法,强制每次测试重新加载路由
如果第一种方法不生效,你可以重写测试类的createApplication方法,确保每次测试都重新初始化应用并加载所有路由:
use Illuminate\Foundation\Application; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; class YourTestCase extends BaseTestCase { public function createApplication(): Application { $app = require __DIR__.'/../bootstrap/app.php'; $app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); // 清空现有路由,重新加载所有路由文件 $app->router->flush(); // 加载Laravel默认路由 require base_path('routes/web.php'); require base_path('routes/api.php'); // 加载Cartalyst的路由文件(路径根据实际vendor目录调整) require base_path('vendor/cartalyst/platform/src/Http/routes.php'); return $app; } }
注意这个方法会让测试变慢,因为每次测试都要重新初始化整个应用,所以优先用第一种方法。
3. 开启PHPUnit进程隔离(备选)
你可以在phpunit.xml里开启进程隔离,让每个测试都在独立的进程中运行,这样每次都会重新加载路由:
<phpunit processIsolation="true" <!-- 其他现有配置 --> > </phpunit>
这个方法同样会增加测试执行时间,所以只在前面两种方法都无效时再考虑。
修改后,你可以在测试的setUp里打印\Route::getRoutes()->count(),首次测试应该就能得到329条,404的问题也会消失。
内容的提问来源于stack exchange,提问作者Lance

