PHPUnit命令找不到需检查PATH或改用本地安装;TestCase类报错是因缺少autoload-dev配置或未引入vendor/autoload.php;断言失败多因类型差异,应使用容差、规范化比较或显式断言;测试污染需靠setUp/tearDown隔离状态。

PHPUnit 安装后 phpunit 命令找不到
不是路径没配好,就是装错了位置。全局安装容易被 Composer 的 bin-dir 路径忽略,尤其在 macOS 或 Linux 上用了 Homebrew 或自定义 COMPOSER_HOME 时。
- 优先用项目本地安装:
composer require --dev phpunit/phpunit,然后通过vendor/bin/phpunit运行 - 检查
composer config --global bin-dir输出的路径是否在$PATH中(Linux/macOS)或系统环境变量里(Windows) - 别信某些教程说“
composer global require就完事”,它默认装到用户目录,且新版 Composer 已弃用全局 require - 运行
which phpunit或where phpunit确认命令来源;如果返回空,说明 shell 根本没识别到
写第一个测试类时 Class 'PHPUnit\Framework\TestCase' 报错
这是 autoloader 没加载 PHPUnit 的核心类,不是你代码写错了。PHP 本身不认 TestCase,全靠 Composer 自动引入。
- 确保
composer.json里有"autoload-dev"配置,哪怕只是空的{},否则vendor/autoload.php可能不加载测试相关命名空间 - 测试文件顶部必须
require_once 'vendor/autoload.php';—— 即使你用的是 Composer 自动加载,也得显式包含一次启动入口 - 类名和文件名要严格匹配:类
CalculatorTest必须放在tests/CalculatorTest.php(或按 PSR-4 规则映射),否则TestCase找得到,你的类找不到 - 别用
phpunit test.php直接跑单个文件,先确认phpunit --version能执行,再用phpunit tests/让它自己发现
assertEquals() 总失败,但 var_dump 看值明明一样
浮点数、数组键顺序、对象引用、null 和 '' 的差异都会让断言静默失败。这不是 PHPUnit 有问题,是 PHP 类型和比较逻辑在捣鬼。
- 浮点数别用
assertEquals(0.1 + 0.2, 0.3),改用assertEquals(0.3, 0.1 + 0.2, '', 0.0001)加 tolerance 参数 - 数组比较前先
ksort()或用assertEqualsCanonicalizing()(PHPUnit 9.3+),否则键顺序不同就报错 - 对象断言优先用
assertNotNull($obj)+assertInstanceOf(),而不是直接assertEquals($expectedObj, $actualObj)—— 后者比的是对象实例,不是内容 - 字符串里可能含不可见字符(BOM、\r\n、零宽空格),用
bin2hex($str)查看真实字节
测试中调用 echo 或修改全局状态导致后续测试异常
PHPUnit 默认每个测试方法单独执行,但没帮你重置 $_SERVER、静态属性、单例或输出缓冲区。一个测试污染了环境,下一个就可能莫名其妙失败。
- 所有输出(
echo、var_dump、print_r)必须用$this->expectOutputString()显式声明预期,否则会被截断且不报错 - 修改了静态属性?在
setUp()里重置,在tearDown()里清理;或者用@backupGlobals enabled注解(但会拖慢速度) - 依赖外部服务(数据库、API)?用
getMockForAbstractClass()或createMock()替换真实调用,别让测试变成集成测试 - 时间敏感逻辑(如
date('Y-m-d'))?用date_default_timezone_set('UTC')统一时区,并在测试里用固定时间戳代替time()
最常被跳过的其实是 setUp() 和 tearDown() 的职责边界:它们不是用来“准备数据”的,而是用来“隔离状态”的。一旦开始在 setUp() 里连数据库或读配置文件,测试就不再是单元测试了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











