核心卡点是autoload路径匹配、测试类加载及CI中--no-dev影响;需配scripts.test、require-dev含phpunit、改autoload-dev后运行composer dump-autoload --dev,并确保命名空间与目录严格一致。

本地测试 Composer 包不是“装完 phpunit 就能跑”,核心卡点在 autoload 路径是否对得上、测试类是否被加载、以及 composer install --no-dev 在 CI 里是否悄悄绕过了你的预期。
composer test 命令为什么本地跑不通
最常见原因是 composer.json 里没配 scripts.test,或者配了但指向了不存在的命令(比如写成 "test": "phpunit" 却没把 vendor/bin 加进 $PATH)。更隐蔽的是:你改了 autoload-dev 但忘了运行 composer dump-autoload --dev,导致 vendor/composer/autoload_dev.php 没更新,class_exists('MyPackageTestsCalculatorTest') 直接返回 false。
- 检查
composer.json的scripts是否存在且指向有效命令,推荐写成"test": "vendor/bin/phpunit" - 确认
require-dev里有"phpunit/phpunit": "^10",再执行composer install --dev - 改完
autoload-dev后必须手动运行composer dump-autoload --dev,CI 中建议加--optimize - 本地验证是否加载成功:
composer dump-autoload --no-dev && php -r "echo class_exists('MyPackageCalculator') ? 'ok' : 'fail';"
tests/ 下的类为什么总报 Class not found
根本不是 PHPUnit 的问题,是 Composer 自动加载配置和文件结构没对齐。例如 tests/Http/ClientTest.php 声明了 namespace MyPackageTestsHttp,但 composer.json 里 autoload-dev 写的是 "MyPackage\Tests\": "tests/" —— 中间少了个反斜杠,路径就断了。
-
autoload-dev.ps4的命名空间末尾必须带反斜杠,且大小写严格匹配文件中namespace声明 - 文件路径必须和命名空间层级一致:
tests/Support/TestCase.php→namespace MyPackageTestsSupport - 无命名空间的辅助类(如
tests/bootstrap.php)不能塞进psr-4,要用autoload-dev.files或classmap - 别在
src/里use MyPackageTestsSupportTestCase—— 生产 autoload 不含autoload-dev,CI 必炸
如何让本地修改实时生效(不用反复 composer update)
用 path 类型仓库 + 符号链接,比硬拷贝快得多,也避免缓存干扰。
- 主项目
composer.json的repositories加一条:{ "type": "path", "url": "../my-local-package", "options": { "symlink": true } } - 本地包的
composer.json必须有正确name和autoload,例如:"autoload": { "psr-4": { "MyPackage\": "src/" } } - 运行
composer require my-vendor/my-local-package:dev-main(或对应分支),之后改src/里的代码,主项目立刻可见 - 注意:Windows 默认不支持符号链接,需以管理员身份运行终端或启用开发者模式
GitHub Actions 里测试通过,但本地报错怎么办
大概率是 PHP 扩展缺失或版本策略不同。Ubuntu runner 默认不装 mbstring、xml、ctype,而你本地用 XAMPP 或 Homebrew 装的 PHP 已经自带这些 —— phpunit 进程启动阶段就挂了,根本到不了测试逻辑。
- CI 中弃用
actions/setup-php,改用shivammathur/setup-php@v2 -
with.extensions显式列出必需扩展:mbstring, xml, ctype, json, openssl - PHP 版本别写死,用矩阵:
php-version: [8.1, 8.2, 8.3] - CI 第一步加
composer validate --no-check-publish,提前拦截composer.json格式错误
最易忽略的一点:所有测试入口(包括 tests/bootstrap.php)都必须用 dirname(__DIR__) . '/vendor/autoload.php' 引入自动加载器,而不是 __DIR__ . '/../vendor/autoload.php' —— 后者在 symlink 或嵌套子模块下会失效,且无法被 IDE 正确识别路径。











