PHPUnit版本需匹配PHP版本:PHP 7.4–8.0用^9.6,8.1+用^10.5,8.2+可试^11.0;必须通过./vendor/bin/phpunit执行,配置phpunit.xml并正确设置autoload-dev。

直接用 composer require --dev phpunit/phpunit 就行,但版本和 PHP 版本必须对得上
装不上、装了跑不了、一跑就报 Class 'PHPUnitFrameworkTestCase' not found——90% 是因为版本错配,不是命令写错了。
PHPUnit 10 要求 PHP ≥ 8.1,PHPUnit 9.6 是 PHP 7.4–8.0 最稳的选择。别信“最新版最好”,composer require --dev phpunit/phpunit 默认可能拉 v11,而你本地是 PHP 8.1,立刻报错:Declaration of PHPUnitFrameworkTestCase::setUp(): void must be compatible。
实操建议:
- 先查 PHP 版本:
php -v - PHP 7.4 或 8.0 →
composer require --dev phpunit/phpunit:^9.6 - PHP 8.1+(Laravel 10+ 项目)→
composer require --dev phpunit/phpunit:^10.5 - PHP 8.2+ 且无框架约束 → 可试
^11.0,但要确认项目里没用已废弃的phpunit-skeleton-generator(它在 v10+ 已彻底移除)
vendor/bin/phpunit 是唯一靠谱的执行入口,别碰全局 phpunit 命令
敲 phpunit 报 command not found?正常。Composer 从不把二进制文件扔进系统 PATH,它只放 vendor/bin/ 下。
更麻烦的是:即使你用 composer global require phpunit/phpunit 装了全局版,它也读不到当前项目的 phpunit.xml 和 autoload.php,导致测试类找不到、配置失效、覆盖率炸掉。
实操建议:
- 永远用
./vendor/bin/phpunit(Linux/macOS)或vendorinphpunit(Windows) - 想指定配置?加
-c:./vendor/bin/phpunit -c phpunit.xml - 只想跑一个文件?直接跟路径:
./vendor/bin/phpunit tests/ExampleTest.php,它会自动加载依赖 - CI 环境里加
--no-coverage,避免因缺 xdebug 导致失败
没 phpunit.xml 不是不行,但大概率跑错目录、漏测或重复加载
不配 phpunit.xml,PHPUnit 默认从当前目录递归扫描所有 *Test.php 文件——这意味着它可能扫到 src/ 里的测试残片、vendor/ 里的第三方测试,甚至你临时写的 tmp/TestDemo.php。
更常见的是:你的测试全在 tests/,但它默认不认这个目录,结果 ./vendor/bin/phpunit 输出 “No tests executed”。
实操建议:
- 最小可用配置只要三件事:
bootstrap="vendor/autoload.php"(确保自动加载就绪)、<directory>tests</directory>(锁定范围)、<testsuite name="default">(命名套件) - 如果测试类没按
Test结尾(比如叫CalculatorSpec.php),就得在<filter>里显式声明后缀 - 生成模板最快方式:
./vendor/bin/phpunit --generate-configuration,它会问你测试目录在哪、要不要 bootstrap,然后吐出phpunit.xml.dist
autoload-dev 配置漏掉,Tests 命名空间就白写了
你写了 use TestsTestCase;,运行却报 Class 'TestsTestCase' not found?不是路径错了,是 Composer 根本没注册这个命名空间。
Composer 的自动加载分两块:autoload(生产代码)和 autoload-dev(测试代码)。tests/ 目录必须进 autoload-dev,否则 composer dump-autoload 也救不了。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 检查
composer.json是否有这段:
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
}
}
composer dump-autoload
Mockery,也要确认它被正确加载——composer require --dev mockery/mockery 后,Mockery::close() 必须在 tearDown() 里调,否则 mock 残留会污染下一个测试最常被忽略的其实是 bootstrap 路径和 autoload-dev 的联动:phpunit.xml 里写的 bootstrap="vendor/autoload.php" 只是起点,真正让测试类能 new 出业务类的,是 autoload-dev 里那条 "Tests\": "tests/"。少一个,整个链就断了。











