You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:42:17