laravel单元测试中数据库操作被自动回滚,是因默认启用事务;可通过禁用$usestransactions、重写setup()、使用refreshdatabase、方法内禁用事务或配置phpunit.xml环境变量解决。

如果您在 Laravel 单元测试中发现数据库操作被自动回滚,导致断言无法验证实际写入效果,则可能是由于 Laravel 默认为每个测试方法启用数据库事务并执行回滚。以下是禁用该行为的多种方法:
一、在测试类中设置 $usesTransactions = false
此方式会完全关闭当前测试类中所有测试方法的事务包装,使数据库变更真实持久化,适用于需要验证插入、更新或外键约束等场景。
1、在测试类定义顶部声明 protected 属性:protected $usesTransactions = false;
2、确保该测试类继承自 Tests\TestCase 或其子类。
3、运行 phpunit 时,该类下所有 test* 方法将不再包裹在事务中。
二、重写 setUp() 方法并手动禁用数据库事务
通过在 setUp() 中调用 DatabaseTransactions 的 disable 方法,可实现更细粒度控制,避免影响其他测试类的行为。
1、在测试类中重写 setUp() 方法:protected function setUp(): void { parent::setUp(); $this->disableDatabaseTransactions(); }
2、确认当前测试类未使用 use DatabaseTransactions; trait。
3、若已引入该 trait,需同时移除或注释掉 use DatabaseTransactions; 声明。
三、使用 DatabaseMigrations 替代 DatabaseTransactions
DatabaseMigrations 在每个测试前执行 migrate:fresh 并在之后不回滚,保留数据至测试结束,适合需要观察多次写入累积状态的场景。
1、在测试类中移除 use DatabaseTransactions; 声明。
2、添加 use RefreshDatabase; trait(Laravel 8+ 推荐)或 use DatabaseMigrations;(旧版本兼容)。
3、确保测试数据库配置独立于开发/生产环境,避免污染。
四、在特定测试方法中临时关闭事务
当仅个别测试需绕过事务机制时,可在方法内部直接操作 DB 门面关闭事务管理器。
1、在测试方法开头调用:\DB::disableQueryLog();
2、手动关闭事务监听器:\Illuminate\Foundation\Testing\DatabaseTransactions::disable();
3、执行数据库操作后,如需恢复事务行为,需在 tearDown() 中显式调用 enable 方法(不推荐混用)。
五、修改 phpunit.xml 中的环境变量强制覆盖
通过环境变量控制框架行为,可全局影响测试中数据库事务策略,适用于 CI 环境统一配置。
1、在 phpunit.xml 的
2、在 TestCase 中读取该变量并动态设置:if (getenv('DB_DISABLE_TRANSACTIONS')) { $this->usesTransactions = false; }
3、确保 phpunit.xml 配置已被加载且无拼写错误。










