测试环境必须使用独立数据库,否则会污染开发库、拖慢ci、误删生产数据;symfony 6.0默认不自动隔离,需手动配置.env.test中database_url(推荐sqlite)、确保doctrine.yaml未硬编码url,并验证环境变量生效,同时处理sqlite目录创建、mysql测试账号权限及事务回滚局限性。

测试环境必须用独立数据库,否则会污染开发库、拖慢 CI、甚至误删生产数据。Symfony 6.0 默认不自动隔离数据库,得手动配。
test 环境下 DATABASE_URL 必须显式覆盖
Symfony 6.0 不再从 .env 自动加载 .env.test,必须确保 DATABASE_URL 在测试环境被正确替换。否则 php bin/phpunit 仍连开发库。
- 检查
.env.test是否存在且内容为:DATABASE_URL="sqlite:///%kernel.project_dir%/var/test.db"(推荐 SQLite)或mysql://test_user:test_pass@127.0.0.1:3306/test_db - 确认
config/packages/test/doctrine.yaml中未硬编码url,否则会覆盖环境变量 - 运行
php bin/console debug:container --env=test | grep DATABASE_URL验证是否生效
测试中自动创建/清空 SQLite 数据库文件
SQLite 文件路径若不存在,Doctrine 不会自动创建目录,导致 ConnectionException;且每次测试前需重置状态。
- 在
tests/bootstrap.php或测试基类的setUp()中加逻辑:if (!is_dir($dir = __DIR__.'/../var')) { mkdir($dir, 0777, true); } - 用
doctrine:database:create --if-not-exists --env=test命令初始化(CI 中建议加在before_script) - 避免用
doctrine:schema:drop --force,改用事务回滚 +TRUNCATE更快;或直接删test.db文件再重建
MySQL/PostgreSQL 测试库需预建且权限受限
用 MySQL 或 PG 时,不能依赖 Doctrine 自动建库(CREATE DATABASE 权限通常被禁),且不同测试并发跑会冲突。
- 手动创建专用库:
CREATE DATABASE symfony_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 分配最小权限账号:
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES ON symfony_test.* TO 'test_user'@'localhost'; - 在
.env.test中使用该账号,**不要复用 root 或开发账号** - 若跑并行测试(如
--process-isolation),需为每个进程生成随机库名,或改用 SQLite
功能测试中事务回滚不是万能的
WebTestCase 默认开启事务回滚,但只对 Doctrine EntityManager 生效;原生 SQL、外部 API 调用、文件写入等不会回滚。
- 确认
config/packages/test/doctrine.yaml含:doctrine: dbal: # ... server_version: 'auto' orm: auto_generate_proxy_classes: true # 无特殊配置即启用事务回滚 - 手动执行原生 SQL?用
$connection->beginTransaction()+$connection->rollback()包裹 - 涉及消息队列、缓存、文件系统操作?必须在
tearDown()中显式清理,不能依赖事务
最易被忽略的是:SQLite 路径权限和 MySQL 测试账号权限——它们失败时往往报错模糊(如 “could not find driver” 或 “access denied”),实际跟数据库隔离完全无关,而是环境准备没到位。











