必须走内核启动的全生命周期流程,即继承kerneltestcase、调用static::createclient()发起绝对路径请求,分步断言状态码与json结构,并通过表单提交或原始json发送非法数据验证服务端校验。

要验证Symfony接口在真实HTTP请求下的完整行为,包括路由匹配、控制器执行、安全拦截、响应生成等环节,必须走内核启动的全生命周期流程,不能只测PHP方法内部逻辑。
创建功能测试类并启动测试内核
在tests/Functional/目录下新建ApiPostListTest.php文件,类名必须以Test结尾,且继承KernelTestCase而非普通TestCase。
在类中调用static::createClient()获取已加载完整服务容器与路由配置的客户端实例——这是唯一能模拟真实请求链路的方式,手动new控制器或Request会导致中间件、事件监听器、防火墙全部失效。
【必须使用static::createClient(),不可用new Client()或直接实例化控制器】
发送GET请求并断言状态码
使用$client->request('GET', '/api/posts')发起请求,注意路径必须以/开头,否则会抛出InvalidArgumentException: Unable to parse URL。
立即检查响应状态码:$this->assertSame(200, $client->getResponse()->getStatusCode())。这一步不能跳过——很多空响应问题(如控制器没return、异常被静默捕获、防火墙重定向)都会先体现在状态码异常上。
若返回401或403,可临时关闭认证:在phpunit.xml.dist中设置
解析JSON响应并校验字段结构
调用$content = $client->getResponse()->getContent()获取原始响应体。
对JSON接口,必须用json_decode($content, true)转为关联数组后再断言,避免直接字符串匹配导致字段顺序或空白符引发误判。
例如验证返回数组至少含3条记录:$this->assertGreaterThanOrEqual(3, count($data));验证每项含id和title字段:$this->assertArrayHasKey('id', $data[0])。
提交非法数据触发服务端校验
方法一:用DomCrawler提交表单
先$client->request('GET', '/api/posts/new')获取表单页→$crawler->filter('form')->form()提取表单对象→立即调用$form->disableValidation()禁用DomCrawler前端校验(否则ChoiceType等字段非法值会直接抛InvalidArgumentException中断流程)→$form->setValues(['title' => ''])→$client->submit($form)。
方法二:直接发送原始JSON请求
$client->request('POST', '/api/posts', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode(['title' => ''])); 这种方式绕过表单组件,更贴近真实API调用场景。
两种方式都需后续断言响应状态码为400,并检查错误信息是否包含'title' => ['This value should not be blank.']。











