测试类必须继承 phpunit\framework\testcase,方法名以 test 开头或加 @test 注解,断言需语义准确(如 assertnull 而非 assertequals(null, $x)),依赖外部服务必须用 createmock 隔离。

测试类必须继承 PHPUnit\Framework\TestCase
不继承这个基类,phpunit 就识别不出你的测试方法,运行时会直接跳过或报错 Class not found。注意命名空间要写全,PHP 7.2+ 必须用 PHPUnit\Framework\TestCase,旧版的 PHPUnit_Framework_TestCase 在 PHPUnit 9+ 已废弃。
常见错误是只写 TestCase 或漏掉 Framework,导致类找不到。建议直接复制标准写法:
use PHPUnit\Framework\TestCase;
<p>class CalculatorTest extends TestCase
{
// ...
}</p>
test 方法名必须以小写 test 开头,或加 @test 注解
PHPUnit 默认只执行 public 方法且方法名以 test 开头(如 testAdd),不区分大小写但推荐小写。如果想用其他命名(比如 addShouldReturnSum),必须加上 @test 注解:
/**
* @test
*/
public function addShouldReturnSum(): void
{
$this->assertEquals(5, (new Calculator())->add(2, 3));
}
没加注解又不以 test 开头的方法,会被静默忽略——你改了代码、写了断言,但测试根本没跑,还误以为“通过”。
断言别只用 assertEquals,按语义选对方法
assertEquals 看似万能,但容易掩盖类型差异。比如 $this->assertEquals(1, '1') 在默认严格模式下会通过(PHP 类型松散比较),但实际可能不该接受字符串输入。
- 要严格比值和类型:用
assertSame - 判断是否为真/假:用
assertTrue/assertFalse,别写assertEquals(true, $x) - 检查是否为空数组或 null:用
assertEmpty/assertNull - 验证异常抛出:用
$this->expectException(\InvalidArgumentException::class)
错误示例:$this->assertEquals(null, $result) —— 应该用 assertNull($result),语义清晰且失败时提示更准。
依赖外部服务?必须用 createMock 隔离
只要测试类里调用了数据库、HTTP 客户端、缓存或任何非内存操作,就必须 mock。否则测试会变慢、不稳定,还可能污染真实数据。
比如被测类依赖 UserService 获取用户信息:
$mockUser = $this->createMock(UserService::class);
$mockUser->method('findById')->willReturn(['id' => 123, 'name' => 'Alice']);
<p>$target = new OrderService($mockUser);
$result = $target->createOrder(123);</p><p>$this->assertEquals('Alice', $result['user_name']);</p>
关键点:
- 不能 new 实际的
UserService,哪怕它只是个接口实现 -
method()和willReturn()要配对,漏掉willReturn会导致返回null - mock 对象不会执行原始逻辑,只按你设定的规则响应
没 mock 的测试,本质上不是单元测试,而是集成测试——它跑得慢、难调试、CI 容易挂,而且根本无法验证单个函数的边界行为。
测试最难的不是写断言,是把业务逻辑从 I/O 和状态依赖里剥出来。mock 写得越顺,说明代码设计越干净;反之,反复改测试才跑通,大概率是被测类本身耦合太重。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











