hyperf单元测试需隔离数据库连接:配置独立test_db连接池(禁用连接池、设短超时)、模型显式指定连接、事务回滚+数据库重置双保险,并为redis定义独立test_redis连接。

Hyperf 单元测试中指定数据库连接并实现环境隔离,核心是让测试不污染主库、不依赖真实配置、能快速重置状态。关键不是“换一个库”,而是“换一套生命周期”——测试连接必须独立初始化、独立销毁、与业务连接完全不共享连接池。
测试专用连接池配置
在 config/autoload/database.php 中,为测试环境单独定义连接池,名称必须全小写、无特殊字符(如 test_db),且不能复用 default 或 db.write 等生产连接名:
- 显式声明完整参数:host 设为
127.0.0.1,database 命名为带_test后缀的库(如hyperf_test),避免与开发/生产库同名冲突 - 关闭连接池复用:
'enable_pool' => false(单元测试是短生命周期,开池反而增加初始化负担和状态残留风险) - 禁用长连接相关参数:移除
max_idle_time、heartbeat等,仅保留connect_timeout和wait_timeout(设为 3.0 秒以内,加快失败反馈)
测试类中强制绑定连接
Hyperf 的 Model 默认走 default 连接,测试时需全程显式指定。三种可靠方式:
-
模型静态调用 on():如
User::on('test_db')->create([...]),适用于单表操作;注意save()实例方法仍走模型自身$connection,不可混用 -
临时覆盖模型属性:在
setUp()中用ReflectionClass修改$connection属性值,测试结束后还原,适合批量断言场景 -
原生查询必须前置 connection():
Db::connection('test_db')->table('users')->insert(...),顺序不可颠倒;Db::select()不接受连接名参数,必须先调connection()
事务回滚 + 数据库重置双保险
仅靠事务 rollback 不足以保证隔离,因为 Hyperf 连接池可能复用已开启事务的连接。推荐组合策略:
- 每个测试方法前开启事务:
$this->beforeApplicationCreated(function () { Db::connection('test_db')->beginTransaction(); }); - 每个测试方法后强制 rollback:
$this->afterApplicationDestroyed(function () { Db::connection('test_db')->rollBack(); }); - 更彻底的做法:在
setUp()中执行Db::connection('test_db')->statement('DROP DATABASE IF EXISTS hyperf_test; CREATE DATABASE hyperf_test;'),配合迁移命令重建表结构(适合集成测试)
Redis 测试连接同样需隔离
若测试涉及 Redis,不能复用 default 连接池。应在 config/autoload/redis.php 中定义独立连接(如 test_redis),database 设为 15(通常预留作测试库),并在测试中通过 DI 注入对应实例:
- 在
dependencies.php中注册:Redis::class => \Hyperf\Redis\RedisFactory::class改为按连接名区分,如'test_redis' => Redis::class - 测试中注入:
public function __construct(private Redis $testRedis) {},调用$this->testRedis->flushdb()清空即可,无需重建库











