yii项目单元测试应避免codecept bootstrap,需保留原有tests/结构并手动补全_bootstrap.php和unit.suite.yml;必须启用yii2模块的orm part以支持ar操作,数据库默认走事务隔离,fixture键名须与模型属性一致,config/test.php需精简组件并确保末尾实例化web\application。

Yii 项目里做单元测试,别硬套 PHPUnit 原生写法 —— Codeception 是官方推荐路径,但直接跑 codecept bootstrap 很可能失败,因为 Yii2 自带的测试结构和配置方式已经固化,强行初始化会覆盖关键引导逻辑。
为什么 codecept bootstrap 在 Yii2 里大概率要删掉重来
Yii2 的 tests/ 目录结构(含 _bootstrap.php、unit.suite.yml)通常随项目骨架生成,codecept bootstrap 会重建整个目录、覆盖原有配置,导致 Yii 应用无法加载(比如 YII_ENV 不生效、config/test.php 找不到)。实际项目中更稳妥的做法是:保留已有 tests/,只补全缺失模块。
- 检查是否存在
tests/unit/和tests/_bootstrap.php,有就跳过 bootstrap - 运行
codecept build即可生成测试执行器(UnitTester类),无需再 init - 若
tests/_bootstrap.php缺失或为空,才需手动补全 Yii 环境初始化代码,核心是三行:define('YII_ENV', 'test')、require vendor/autoload.php、require Yii.php,最后加载config/test.php
Yii2 模块在 unit.suite.yml 中必须显式启用 part: [orm]
否则 $this->tester->haveRecord()、$this->tester->seeRecord() 这类快捷方法不可用,且模型验证、AR 关联、事务回滚等 Yii 特性不会自动注入。单纯启用 Yii2 模块不够,必须指定 part。
-
part: [orm]启用 ActiveRecord 支持,包括 fixtures、model save/load、数据库事务隔离 -
part: [web]仅在功能测试(functional suite)中需要,单元测试里加了反而报错 - 若测试涉及 Redis 或缓存,还需额外启用
Yii2的cachepart,并确保config/test.php中缓存组件已正确定义
测试数据库不是“复制生产库”,而是靠 fixtures + transaction 隔离
很多人误以为要配一个独立的 test 数据库并 dump 全量表结构 —— 实际上 Yii2 单元测试默认走内存事务(beginTransaction() + rollback()),每测完一个 case 自动清空变更。真正需要你操心的是 fixture 定义是否匹配当前模型表结构。
- fixture 文件(如
tests/_data/user.php)返回数组,键名必须与模型属性名一致(不是数据库字段名),例如'username'而非'user_name' - 若模型使用了
tableName()自定义表名,fixture 数组的 key 必须对应模型里的属性,Codeception 不会自动映射字段别名 - 不建议在 unit 测试中依赖真实数据库连接池;如果必须查库,请确认
config/test.php中'db'组件已正确配置,且用户有建表权限(用于自动创建测试表)
config/test.php 里不能照抄 config/web.php 的全部组件
很多团队把 web.php 复制一份改名 test.php,结果测试跑一半就卡住 —— 因为某些组件(如 log、mailer、redis)在 test 环境下未做降级或 mock,导致网络超时或写盘失败。
- 日志组件应禁用文件写入,改用
Target的dump或echo方式,避免测试中途因磁盘满失败 - 邮件组件必须替换为
FileTarget或NullMailer,否则发信会阻塞甚至抛出Swift_TransportException - 若用到
urlManager,请确保enablePrettyUrl设为false,否则路由解析可能因缺少 Apache/Nginx 环境而异常
最常被忽略的一点:tests/_bootstrap.php 末尾那行 (new yii\web\Application($config)) 必须存在,且不能换成 console\Application —— 即便你测的是 console command,unit suite 默认走 web Application,否则 Yii::$app->user、Yii::$app->request 等全局对象为空,断言直接崩。











