A2A 测试别把 HTTP 200 当作调用成功
A2A 调用可能返回 HTTP 200,同时在 JSON-RPC 响应体中携带错误,表明传输成功但方法执行失败。测试应解析响应体并区分 result 与 error,对协议层结果作出断言。
AI 深度解读
A2A 调用返回 HTTP 200,任务却可能根本没创建成功。问题在于,HTTP 状态和 JSON-RPC 方法结果是两层信息:前者显示请求在传输层被正常处理,后者才说明方法是否成功。测试只检查状态码,就可能把被拒绝的调用记成通过。
作者给出的办法很直接:打开响应体,区分 result 和 error,再按预期结果断言。对需要调用 A2A 的程序员,这个检查比看到一片绿色更有用。
为什么 HTTP 200 仍然可能是失败
按原文讨论的调用方式,A2A 通过 JSON-RPC 传递方法请求,HTTP 是承载这些消息的通道。服务器可以正常接收 HTTP 请求并返回 200,同时在 JSON-RPC 响应体中说明:方法被拒绝、参数无效,或者任务无法创建。
可以把它理解为两个问题:请求有没有正常送达,以及服务器有没有完成你要求的方法。第一个问题得到肯定回答,不能代替第二个。
因此,同一个 HTTP 200,需要结合响应体判断:
- 响应体包含
result,对应作者所说的方法成功。 - 响应体包含
error,表示传输成功,但方法失败。
HTTP 200 只能作为一层检查,不能直接充当方法成功的断言。
作者用缺少必填字段的任务创建请求说明这个问题。服务器返回 200,但响应体给出参数错误,任务并未创建。补齐字段后,响应体才返回带有任务引用的 result。只看状态码,这两次请求没有区别;检查响应体,才能看出结果不同。
这里没有提供具体请求、错误码或执行日志,因此应把它看作解释机制的示例,不能当作一组已经展示完整证据的实测结果。
测试应该检查哪一层,报告就记录哪一层
原文建议先在 Debug 界面中使用生成的请求体构建请求,并带上 A2A-Version 请求头。发送后,先确认 HTTP 状态,再检查响应体包含 result 还是 error;如果存在错误,还要读取错误码和消息。
文章保留了版本请求头的名字,但没有给出具体版本值,也没有说明 Debug 界面如何生成请求体。落地时,这些细节需要从项目实际使用的接口约定中补齐。
断言也要跟着场景走。有效请求应断言返回预期的 result;缺少必填字段的请求,应断言返回对应的错误码。不能把两种情况都按 200 判定通过,也不能把所有 error 都判成测试失败:对于验证参数校验的用例,返回预期错误正是测试通过的条件。
报告则应分别记录传输结果和协议结果。如果错误只在特定输入下出现,作者建议保留请求和完整响应体。这样才能知道是哪组输入触发了拒绝,以及服务器当时返回了什么,而不是只剩一个没有解释力的状态码。
我的判断
作者抓住了一个实际的测试盲区:用 HTTP 状态代替接口契约。只要方法结果放在 JSON-RPC 消息中,断言就必须读到这一层。
但检查到 result 还可以继续往下走。作者把「200 加 result」视为完整成功,实际项目仍应按接口契约验证结果中的必要字段。例如,任务创建返回的任务引用是否符合约定。否则,测试只是从检查状态码推进到了检查字段是否存在。
原文没有给出对照数据,不能据此判断这种检查能减少多少漏报,也无法衡量接入成本。它的价值在于明确断言边界,证据不足以支持更大的效果承诺。
文末提到 Powerduck 会在 Debug 界面展示 JSON-RPC 层,但没有提供与其他工具的对比。选工具时可以关注它是否方便查看和断言响应体;具体产品并不是采用这套方法的必要条件。
能拿来做什么
- 检查现有 A2A 自动化用例,把只断言 HTTP 200 的成功路径补上
result和必要结果字段的校验。 - 为缺少必填字段的请求增加负向用例,断言约定的错误码,避免参数校验失效后测试仍然通过。
- 如果前端或 Node 调用层目前只按 HTTP 状态判断成功,把 JSON-RPC
error纳入处理,让方法拒绝能进入明确的错误分支。 - 在偶发失败的测试报告中分别记录 HTTP 状态、协议结果、请求和完整响应体,保留重现所需的信息。