Laravel测试配置多SQLite内存数据库遇重复表问题求助
解决Laravel+PHPUnit双SQLite内存数据库测试配置问题
嘿,我之前刚好踩过类似的坑,给你分享下我是怎么搞定双SQLite内存数据库测试配置的,应该能帮你解决问题:
1. 调整测试环境的数据库配置
首先在config/database.php里,给你的两个数据库连接(backend、frontend)在测试环境下配置为SQLite内存库。如果你的配置是区分环境的,直接在testing数组里修改;如果是统一配置,就直接替换对应的连接项:
'connections' => [ 'backend' => [ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], 'frontend' => [ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], // 保留其他默认连接(比如mysql)用于非测试环境 ],
2. 给测试类配置双数据库迁移
因为你有两套迁移文件,需要在测试启动时分别运行两个数据库的迁移。建议创建一个自定义的TestCase基类,所有测试类都继承它,在setUp和tearDown方法里处理迁移:
use Illuminate\Foundation\Testing\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase { use CreatesApplication; protected function setUp(): void { parent::setUp(); // 运行后端数据库的迁移(指定迁移目录) $this->artisan('migrate', [ '--database' => 'backend', '--path' => 'database/migrations/backend', // 替换成你实际的后端迁移目录 ]); // 运行前端数据库的迁移 $this->artisan('migrate', [ '--database' => 'frontend', '--path' => 'database/migrations/frontend', // 替换成你实际的前端迁移目录 ]); // 如果需要测试数据,在这里添加填充命令 // $this->artisan('db:seed', ['--database' => 'backend', '--class' => 'BackendSeeder']); // $this->artisan('db:seed', ['--database' => 'frontend', '--class' => 'FrontendSeeder']); } protected function tearDown(): void { // 测试结束后回滚两个数据库的迁移,清理内存数据 $this->artisan('migrate:rollback', [ '--database' => 'backend', '--path' => 'database/migrations/backend', ]); $this->artisan('migrate:rollback', [ '--database' => 'frontend', '--path' => 'database/migrations/frontend', ]); parent::tearDown(); } }
3. 确保模型绑定正确的数据库连接
别忘记给对应模型指定连接属性,这样Eloquent才知道该用哪个数据库:
// 后端内容模型示例 class BackendContent extends Model { protected $connection = 'backend'; // 其他模型属性... } // 前端用户模型示例 class FrontendUser extends Model { protected $connection = 'frontend'; // 其他模型属性... }
4. 配置PHPUnit环境变量
在phpunit.xml里设置测试环境的基础变量,确保Laravel加载测试配置:
<php> <env name="APP_ENV" value="testing"/> <env name="DB_FOREIGN_KEYS" value="true"/> <!-- 默认连接可以设为backend,不过测试里我们会明确指定,所以影响不大 --> <env name="DB_CONNECTION" value="backend"/> </php>
5. 编写测试用例示例
现在你就可以正常编写测试了,比如创建前端用户并测试后端内容的场景:
class ContentAccessTest extends TestCase { public function test_frontend_user_can_view_backend_content() { // 创建前端测试用户 $frontendUser = FrontendUser::factory()->create(); // 创建后端测试内容 $backendContent = BackendContent::factory()->create(); // 模拟前端用户访问内容接口(根据你的业务逻辑调整) $response = $this->actingAs($frontendUser, 'frontend') // 如果用了多认证guard的话 ->get("/api/content/{$backendContent->id}"); // 断言响应状态和内容 $response->assertStatus(200); $response->assertJsonFragment(['title' => $backendContent->title]); } }
注意事项
- SQLite内存库是每个PDO连接对应一个独立实例,所以只要你的两个数据库连接是单独配置的,就会是完全隔离的两个内存库,不用担心数据混在一起。
- 如果遇到迁移不生效的问题,检查下迁移目录路径是否正确,或者在
artisan命令里加上--force参数(测试环境下一般不需要,但有时候能解决权限问题)。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

