Laravel Dusk中DatabaseTransactions无法回滚事务问题求助
嘿,我之前也踩过Dusk测试后数据库不回滚的坑,结合你的情况,核心问题其实是Dusk的运行机制导致DatabaseTransactions trait根本没法生效,咱们来一步步解决:
为什么DatabaseTransactions在Dusk里没用?
Dusk是启动真实浏览器发起HTTP请求,你的测试代码和应用代码其实是跑在两个完全独立的进程里的。测试进程里开启的数据库事务,浏览器进程的请求根本看不到(因为事务没提交),所以你测试时能成功创建用户,是因为浏览器进程的操作直接把数据提交到了数据库,而测试进程最后执行的事务回滚,对这条已经提交的数据完全没影响。
靠谱的替代方案
方案1:用DatabaseMigrations trait重置数据库
把use DatabaseTransactions;直接换成use DatabaseMigrations;,这样每次测试前都会重新跑一遍数据库迁移,测试结束后自动回滚迁移,保证数据库每次都是干净的。缺点是如果迁移文件多,测试速度会慢一点,但胜在省心:
<?php namespace Tests\Browser; use Illuminate\Foundation\Testing\DatabaseMigrations; use Laravel\Dusk\Browser; use Tests\DuskTestCase; class RegistrationTest extends DuskTestCase { use DatabaseMigrations; // 替换原来的DatabaseTransactions /** * 测试注册功能 */ public function testSuccessfulRegistration() { $this->browse(function (Browser $browser) { $browser->visit('/register') ->type('name', '测试用户') ->type('email', 'test_dusk@example.com') ->type('password', 'password123') ->type('password_confirmation', 'password123') ->press('注册') ->assertPathIs('/dashboard'); }); } }
方案2:手动清理测试数据
如果不想每次跑迁移,也可以在测试结束后手动删除创建的测试数据,比如用tearDown方法或者在测试方法末尾直接清理:
<?php namespace Tests\Browser; use Laravel\Dusk\Browser; use Tests\DuskTestCase; use App\Models\User; class RegistrationTest extends DuskTestCase { protected function tearDown(): void { parent::tearDown(); // 清理测试创建的用户 User::where('email', 'test_dusk@example.com')->delete(); } public function testSuccessfulRegistration() { $testEmail = 'test_dusk@example.com'; $this->browse(function (Browser $browser) use ($testEmail) { $browser->visit('/register') ->type('name', '测试用户') ->type('email', $testEmail) ->type('password', 'password123') ->type('password_confirmation', 'password123') ->press('注册') ->assertPathIs('/dashboard'); }); // 也可以在这里直接清理 // User::where('email', $testEmail)->delete(); } }
方案3:用RefreshDatabase trait(推荐)
Laravel的RefreshDatabase trait会自动判断测试类型:如果是普通功能测试,用事务回滚;如果是Dusk这种外部请求测试,自动切换成迁移重置数据库,兼顾速度和可靠性:
use Illuminate\Foundation\Testing\RefreshDatabase; // 替换原来的trait
额外注意事项
- 确保你的测试环境用的是独立的测试数据库(比如在
.env.dusk.local里配置DB_DATABASE=laravel_test),别和开发库共用,避免误删真实数据; - 之前配置的
$connectionsToTransact对Dusk没用,可以直接删掉,因为跨进程事务根本行不通。
内容的提问来源于stack exchange,提问作者Jk33
相关产品推荐
相关产品推荐

