PHPUnit 9.6+是PHP 8.0单元测试的直接选择,支持联合类型等新特性;需用assertSame()替代assertEquals()确保类型一致,dataProvider和mock需显式匹配类型,setup中应加类型断言。

PHPUnit 是 PHP 8.0 下实现单元测试、保障代码质量的直接选择。它完全兼容 PHP 8.0+,支持联合类型、属性类型声明、mixed、never 等新特性,无需降级适配。
安装 PHPUnit 9.6+(适配 PHP 8.0)
低版本 PHPUnit(如 8.x)不支持 PHP 8.0 的联合类型语法,运行时会报 ParseError: Syntax error;必须用 9.5 或更高版本。
- 执行
composer require --dev phpunit/phpunit ^9.6(推荐锁定^9.6,避免意外升级到不兼容的 10.x) - 验证是否生效:
vendor/bin/phpunit --version应输出类似PHPUnit 9.6.15 - 若项目已启用
declare(strict_types=1),测试类也需保持一致,否则可能触发严格类型警告
测试含联合类型的函数要小心断言方式
PHP 8.0 中常见 int|string 或 array|null 返回值,但 assertEquals() 默认做松散比较,可能掩盖类型错误。
- 例如:函数返回
string "123",而期望是int 123,assertEquals(123, $result)会通过,但实际类型不符 - 应改用
assertSame()强制类型+值一致:$this->assertSame(123, $result) - 对可空返回(如
?User),先用assertNotNull()或assertInstanceOf()明确校验非空分支,再测具体属性
setup() 和数据提供者(@dataProvider)要适配 PHP 8.0 类型推断
PHP 8.0 支持在方法签名中写联合类型,但 @dataProvider 返回数组时,PHPUnit 不自动做类型校验 —— 它只负责把数据传进去,类型错误会在被测方法里爆发。
- 确保
dataProvider方法返回的数据结构与被测函数参数类型完全匹配,比如函数接受int|string,就别传float进去 -
setup()中实例化对象时,若构造函数含联合类型参数,传参错误会在setup()阶段直接抛TypeError,而不是测试失败 —— 这说明测试环境本身就不干净 - 建议在
setUp(): void后加类型断言,如assertIsObject($this->service),提前暴露初始化问题
mock 对象时注意 PHP 8.0 的返回类型约束
用 $this->createMock() 或 $this->getMockBuilder() 模拟一个带联合类型返回的方法(如 find(): User|array),PHPUnit 默认返回 null,调用时会因类型不匹配触发 TypeError。
立即学习“PHP免费学习笔记(深入)”;
- 必须显式配置 mock 的返回值类型,例如:
$mock->method('find')->willReturn(new User())或->willReturn([]) - 不能只写
->willReturnAny(),它不保证类型安全,PHP 8.0 下会立刻崩 - 若被模拟类用了
final方法或属性,PHP 8.0 + PHPUnit 9.6 默认无法 mock,需改用disableOriginalConstructor()或重写为protected
assertEquals() 很容易,但决定用 assertSame()、检查 gettype()、或在 provider 里加 is_int() || is_string() 断言,才是守住质量边界的动作。



















