thinkphp沙箱数据库需配置独立连接(如sandbox),通过环境变量或setup()切换;测试后用teardown()清空业务表或迁移刷新;禁用mock db类,确保真实sql验证;事务须显式回滚并关闭自动提交。

ThinkPHP怎么配沙箱数据库连接
ThinkPHP本身不内置“数据沙箱”概念,所谓沙箱测试,本质是用一套隔离的数据库配置跑测试逻辑,避免污染生产或开发库。关键不是加什么插件,而是让测试时自动切到另一套 database.php 配置。
- 在
config/database.php中定义两个连接:一个default(开发用),一个sandbox(专供测试);sandbox的hostname可指向本地 Docker 实例或 SQLite 文件路径 - 测试启动前,通过环境变量强制切换:
DB_CONNECTION=sandbox php artisan test(Laravel 风格可类比),ThinkPHP 则需在tests/TestCase.php的setUp()里手动调用Db::connect('sandbox') - 别直接改
env文件——测试环境和 CI 流水线必须能独立控制,否则一跑测试就把开发库清空了
如何让单元测试自动清空沙箱表
测试完不清库,下一次跑就可能因主键冲突、唯一索引报错而失败。ThinkPHP 没有 Laravel 那样的 RefreshDatabase trait,得自己搭“擦除器”。
- 在
tests/TestCase.php的tearDown()方法里,遍历所有被测模型的表名,执行Db::name($table)->delete(true)(true表示清空全表) - 更稳妥的做法是只清空业务表,跳过系统表(如
think_system_config),用白名单数组控制:$cleanTables = ['orders', 'users', 'payments'] - 如果用了迁移(migration),可在测试前执行
php think migrate:refresh --connection=sandbox,但注意 ThinkPHP 5.1 默认不带迁移命令,需额外装topthink/think-migration
为什么不能在沙箱里直接 mock Db 类
有人想用 Mockery::mock('\think\Db') 拦截所有查询——这会导致测试脱离真实 SQL 行为,掩盖字段不存在、JOIN 写错、事务未提交等硬伤。
- 数据库层 mock 适合验证“是否调用了 Db::table()”,不适合验证“查出来的数据对不对”
- 真正要测的是业务逻辑与数据交互的组合效果,比如“用户下单后库存减 1,订单状态变 pending”,这类断言必须走真实 DB
- 若真要绕开 DB(比如测超慢查询的兜底逻辑),应 mock 具体的服务类(如
OrderService),而不是框架底层类
沙箱测试常卡在“事务没回滚”
ThinkPHP 的事务默认不自动回滚,测试中一旦开启 Db::startTrans(),又没显式 commit 或 rollback,后续测试会卡住或报 SQLSTATE[HY000]: General error: 2006 MySQL server has gone away。
- 在
setUp()开头加Db::execute('SET autocommit = 1');,确保每个测试从干净事务状态开始 - 所有涉及事务的测试方法,结尾必须显式调用
Db::rollback(),哪怕没出错——因为 PHPUnit 可能因断言失败提前退出,导致事务挂起 - 避免在模型事件(如
afterInsert)里开启新事务,ThinkPHP 不支持嵌套事务,沙箱里更容易暴露死锁
Cache 实例)。这些不处理,测试结果看着绿,上线照样崩。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











