测试环境数据库必须用独立库名,不能复用开发库;.env.test只写覆盖项,需显式设app_env=test并配合%env(resolve:database_url)%解析,否则连接失败。

测试环境数据库必须用独立库名,不能复用开发库
直接复制 .env.local 改名成 .env.test 是常见错误。Symfony 在 APP_ENV=test 下会启用 Doctrine 的数据库隔离策略:它不会连接你写的 app 库,而是自动追加 _test 后缀(如 app_test),并尝试连接该库。如果这个库不存在,或 DATABASE_URL 仍指向宿主机不可达的地址(比如 @database),就会报 “Connection refused”。
正确做法是显式指定一个可访问、可清空的测试库:
-
DATABASE_URL必须指向真实存在的 MySQL 实例,且用户名有权限创建/删除库(Doctrine 测试时会自动DROP DATABASE再重建) - 推荐使用
host.docker.internal(Docker Desktop on macOS/Windows)或宿主机真实 IP(Linux 需手动配置--add-host=host.docker.internal:host-gateway) - 库名必须带
_test后缀,例如app_test,否则 Doctrine 不会识别为测试专用库
.env.test 文件里只写覆盖项,不重复定义全局变量
.env.test 不是“全量配置文件”,它只应覆盖测试环境需要变更的变量。其他如 APP_SECRET、MAILER_DSN 等若无需特殊值,就不要写——让它们从 .env 或 .env.local 继承即可。
典型 .env.test 内容示例:
APP_ENV=test DATABASE_URL="mysql://root:root@host.docker.internal:3306/app_test"
注意:APP_ENV=test 这行必须存在,否则 Symfony 不会加载该文件;但 APP_DEBUG 不建议在 .env.test 中设为 1,因为测试容器默认已禁用 Profiler,设了也无效。
运行测试命令前必须显式设置 APP_ENV=test
CLI 命令不读 .env.test 文件,除非你告诉它当前环境是 test。不能依赖 php bin/console --env=test(该参数已弃用),必须前置设置环境变量:
APP_ENV=test php bin/console doctrine:database:createAPP_ENV=test php bin/console doctrine:migrations:migrateAPP_ENV=test ./vendor/bin/phpunit
漏掉 APP_ENV=test,命令会 fallback 到 dev 环境,导致连错库、加载错配置、甚至误删开发数据。
测试数据库初始化失败?先检查 doctrine.yaml 是否用了 resolve:
即使 .env.test 写对了,如果 config/packages/doctrine.yaml 里写的是:
doctrine:
dbal:
url: '%env(DATABASE_URL)%'
那变量根本不会被解析,%env(...)% 会被当字面量处理,最终连接字符串就是 %env(DATABASE_URL)%,必然失败。
必须改成:
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
resolve: 前缀才是触发 Dotenv 解析的关键。没有它,所有环境变量引用都只是字符串。
真正容易被忽略的是:测试环境的数据库隔离逻辑不是靠文件名驱动的,而是靠 APP_ENV=test + resolve: + Doctrine 的 TestBundle 自动钩子三者共同生效。少一个环节,_test 库就不会被创建或清空。











