如何在使用Stancl Tenancy的Laravel多租户应用中实现并行测试
问题原因
- 核心原因是Laravel并行测试默认只会自动调整默认数据库连接的库名后缀,Stancl Tenancy独立使用的
landlord中心库连接不会被自动修改,所有测试进程默认操作同一个中心库,多进程同时创建租户时触发主键唯一约束冲突,除了第一个执行成功的进程外其他进程直接抛出异常终止,所以只有编号5的进程成功创建了租户。 - 其次回调中执行
Tenant::create前没有校验当前landlord连接的可用性,部分进程的中心库还未执行迁移也会导致创建租户时报表不存在错误,进程直接退出。
解决方法
- 首先在
setUpTestDatabase回调中手动切换landlord连接到当前进程对应的独立测试库,避免多进程数据冲突 - 执行中心库迁移保证
tenants等核心表存在后,再创建租户 - 示例代码如下:
ParallelTesting::setUpTestDatabase(function ($database, $token) { // 1. 切换landlord连接到当前进程专属测试库,前缀替换为你自己的landlord测试库名 $landlordDb = "your_landlord_test_db_name_{$token}"; config(['database.connections.landlord.database' => $landlordDb]); DB::connection('landlord')->reconnect(); // 2. 执行中心库迁移,确保租户表存在 Artisan::call('tenancy:migrate', [ '--landlord' => true, '--force' => true, ]); // 3. 安全创建租户 $tenant = Tenant::create([ 'id' => "testTenant{$token}", 'name' => "PHPUnit Process {$token}" ]); // 可选:初始化当前租户上下文,避免后续测试报租户未识别错误 tenancy()->initialize($tenant); });
- 额外优化建议:将该回调注册逻辑放到仅测试环境加载的服务提供者中(比如
TestServiceProvider),不要放在全局AppServiceProvider中,避免生产环境加载无效逻辑。
内容的提问来源于stack exchange,提问作者Rory
相关产品推荐
相关产品推荐

