ThinkPHP 6 接口自动化测试需用 PHPUnit 配合 Http 门面发起请求,通过 Response 对象的 getCode()、getContent() 等方法断言状态码、内容及响应头,数据库测试须手动清空或使用测试专用库。

ThinkPHP 做接口自动化测试,核心是用 PHPUnit 模拟真实 HTTP 请求、接收响应、再对状态码、内容、结构做精准断言。TP6 起已不再提供封装好的测试基类,需回归原生 PHPUnit 写法,但保留了框架内建的 Http 门面和响应对象,配合得当反而更可控。
用 Http::get/post 发起请求
TP6 废除了 $this->get() 这类快捷方法,所有请求必须显式调用 think\facade\Http:
- GET 请求:
$response = Http::get('/api/user/1'); - POST JSON 请求:
$response = Http::withHeaders(['Content-Type' => 'application/json'])->post('/api/user', ['name' => 'Tom']); - 带 Cookie 或 Token 的请求:
Http::withCookie('PHPSESSID', 'abc123')->withHeader('Authorization', 'Bearer xxx')->get('/api/profile'); - 若需完整走中间件链(如鉴权、日志),不能跳过应用入口,推荐:
App::make('http')->handle(Request::create('/api/test', 'GET'));
对响应做状态与内容断言
响应对象是 think\Response 实例,不是 PSR-7 标准对象,别用 getStatusCode() —— 它不存在:
- 断言状态码:用
$response->getCode() === 200或$this->assertEquals(200, $response->getCode()); - 断言 JSON 响应体:
$data = json_decode($response->getContent(), true); $this->assertArrayHasKey('id', $data); - 断言纯文本输出(如控制器 return 'ok'):
$this->assertEquals('ok', $response->getContent()); - 断言重定向(302):
$this->assertEquals(302, $response->getCode()); $this->assertEquals('https://example.com', $response->getHeader('Location'));
数据库测试前清空或重置数据
TP6 不再自动隔离测试数据库连接,多个测试共用同一库时极易互相污染:
立即学习“PHP免费学习笔记(深入)”;
- 每次测试前手动清空表:
Db::name('user')->delete(true);(true表示无条件清空) - 或使用迁移回滚 + 数据填充:
php think migrate:rollback --step=1 && php think seed:run,再在setUp()中执行 - 避免用
refreshDatabasetrait(这是 Laravel 的,TP 无原生支持),需自行封装 - 敏感操作如删除用户表,建议在测试专用数据库中运行,配置
database.php的'default' => 'test'并单独设账号
常见断言写法对照(TP5 vs TP6)
旧版扩展中的 see()、seeJson() 等方法在 TP6 中不可用,需改写为原生断言:
-
$this->visit('/api/test')->see('hello');→$response = Http::get('/api/test'); $this->assertStringContainsString('hello', $response->getContent()); -
$this->seeJson(['code' => 0]);→$data = json_decode($response->getContent(), true); $this->assertEquals(0, $data['code'] ?? null); -
$this->assertResponseOk();→$this->assertEquals(200, $response->getCode()); - 检查响应头:
$this->assertEquals('application/json', $response->getHeader('Content-Type'));



















