autoload-dev必须作为composer.json顶层字段独立配置,与autoload并列;测试类须放其中,改后需执行composer dump-autoload --dev生效,否则不加载。

autoload-dev 必须单独配在主项目 composer.json 顶层
本地调试时,测试类(比如 tests/MyPackageTest.php)绝不能塞进 autoload 字段里,否则它们会随 composer install --no-dev 一起打进生产环境。正确做法是把整个 autoload-dev 作为顶级字段写在主项目 composer.json 中,和 autoload 并列:
{
"autoload": {
"psr-4": { "MyPackage\": "src/" }
},
"autoload-dev": {
"psr-4": { "MyPackage\Tests\": "tests/" }
}
}注意:MyPackage\Tests\ 末尾的双反斜杠 \ 是强制要求,少一个就匹配失败;tests/ 是相对于 composer.json 的路径,不能写成 ./tests/ 或 /tests/。
改完 autoload-dev 后必须显式执行 dump-autoload --dev
composer dump-autoload 默认只刷新 autoload,对 autoload-dev 完全无效。不加 --dev(或 -a),你的测试命名空间根本不会写入 vendor/composer/autoload_dev_psr4.php,结果就是 Class not found。
- 运行
composer dump-autoload --dev或composer dump-autoload -a - 验证是否生效:打开
vendor/composer/autoload_dev_psr4.php,搜索"MyPackage\\Tests\\"看是否存在 - 别依赖
composer install自动触发——它只在首次安装或更新包时生成 autoload 文件,不响应autoload-dev变更
本地包的测试类不能靠主项目 autoload-dev 覆盖
如果你在调试一个本地开发的扩展包(比如 packages/my-utils),它的测试类(如 packages/my-utils/tests/UtilsTest.php)必须由**该包自身的 composer.json** 配置 autoload-dev,而不是主项目。
- 本地包根目录下
composer.json必须含"autoload-dev": { "psr-4": { "MyUtils\Tests\": "tests/" } } - 主项目只需通过
repositories+require引入这个包,无需重复声明其测试路径 - 改完本地包的
autoload-dev后,要在主项目中再次运行composer dump-autoload --dev,因为 Composer 会合并所有已加载包的 dev autoload 规则
CI/CD 中 autoload-dev 生效的前提是没加 --no-dev
很多 CI 流水线为了减小镜像体积,在构建阶段执行 composer install --no-dev,这时 autoload-dev 配置会被完全跳过,即使你配得再准也没用。
验证方式很简单:
- 在 CI 脚本中加一句
composer show -s | grep Tests,确认输出包含你的测试命名空间 - 若无输出,说明
--no-dev已禁用 dev 模式,要么去掉该参数,要么把测试启动逻辑(如 PHPUnit bootstrap)改用显式 require 方式加载测试类 - 注意:有些旧版 Composer 在
COMPOSER_DEV_MODE=1下仍可能绕过--no-dev限制,v2.2+ 已修复,建议保持版本更新
最常被忽略的一点:autoload-dev 不是“按需启用”,而是“一次性注册”。一旦 vendor/autoload.php 被加载,所有 dev 类就跟生产类一样进入 SPL 加载器链——所以别在运行时动态开关,它没有 runtime 开关机制。


















