模型接口集成测试:从请求拦截到故障验证的七步实战
模型接口的集成测试,应该验证业务代码如何发送请求、解析响应和处理故障,而不是检查模型今天回答得是否漂亮。在 CodeRelay Hub 这类统一接口场景中,建议保留真实客户端和业务调用链,只替换网络边界。下面按顺序搭建一套可重复执行的测试。
1. 确定模拟边界
从业务入口发起测试,让请求经过参数组装、客户端序列化和响应解析,再由模拟服务接住。不要直接把业务方法替换成固定答案,否则无法验证请求格式。以 Python 为例,HTTPX 提供 MockTransport,可通过处理函数检查请求并返回预设响应。使用前应核对项目锁定的客户端版本及其传输实现。([python-httpx.org](https://www.python-httpx.org/advanced/transports/?utm_source=openai))
如果还需要验证真实连接、读取超时或代理行为,则另设本地模拟服务器;不要把内存传输测试当作完整网络测试。
2. 注入测试配置并禁止外连
把客户端构造集中到一个工厂,通过配置传入接口基址、密钥和重试策略。OpenAI Python SDK 支持 base_url 和自定义 http_client,因此不必修改业务调用代码,就能替换请求目的地或传输层。具体参数类型应以项目使用的 SDK 版本为准。([github.com](https://github.com/openai/openai-python/blob/main/src/openai/_client.py?utm_source=openai))
测试只使用虚构密钥,未匹配的请求立即失败,禁止回退到真实服务。并行执行时,为每个用例创建独立客户端和请求记录器,避免计数器互相污染。测试结束后关闭客户端,恢复配置。
3. 先校验请求,再返回成功夹具
让处理函数先检查请求方法、完整路径、认证头,以及解析后的请求体。路径以应用实际配置为准,不要仅凭接口基址猜测是否需要额外前缀。对模型标识、消息顺序和 stream 等关键字段使用明确断言。
再返回一份与所用接口契约一致的最小响应夹具。例如,测试 Chat Completions 时,让 choices[0].message.content 固定为“已完成”,并包含应用读取的结束原因和用量字段。业务层应断言最终结果,而不仅是收到成功状态码。另建缺字段夹具,验证解析失败是否得到正确处理。
4. 把故障写成状态序列
为认证失败、限流、服务端错误和连接异常分别建立用例。每个用例都应声明响应序列、预期调用次数和最终业务状态,例如先返回限流错误,再返回成功响应,并检查是否只产生一次业务结果。
先关闭 SDK 重试,单独验证应用的错误映射;再打开目标重试策略,测试恢复与耗尽。OpenAI Python SDK 提供 max_retries,设置为 0 可禁用其自动重试。不要同时默认开启多层重试,却只断言最外层调用次数。([github.com](https://github.com/openai/openai-python/blob/main/README.md?plain=1&utm_source=openai))
测试退避时注入可控等待函数或时钟,记录等待计划,避免真的等待长时间。连接异常与读取超时也应分开模拟,而不是统一返回一个错误状态码。
5. 单独覆盖流式协议
不要用完整响应冒充流式输出。Chat Completions 的流式内容通过 delta 增量传递,而不是普通响应中的 message;夹具必须遵循相应事件结构。([developers.openai.com](https://developers.openai.com/api/docs/guides/streaming-responses?utm_source=openai))
至少覆盖正常结束、空增量、事件跨网络分块和中途断开。让同一事件拆成两次读取,再让多个事件合并进入一次读取,检查解析器是否错误地假设“一次读取就是一个事件”。断流后应明确标记结果未完成,不能把已经收到的部分文本当作完整答案。
6. 验证工具调用与业务副作用
工具调用不能只断言工具名称。流式工具调用包含调用索引、标识和参数片段;参数还需要在执行前校验,不能因为来自模型就视为可信输入。([developers.openai.com](https://developers.openai.com/api/reference/resources/chat/subresources/completions/streaming-events?utm_source=openai))
准备参数分段到达、参数无法解析和参数不符合业务约束三类夹具。只有参数完整且通过校验,才允许进入工具执行器。执行器本身使用测试替身,并断言调用次数与实参。对于写入操作,还应检查重试或重复事件是否导致重复副作用,而不是只检查最终文本。
7. 用少量真实测试校准契约
把模拟测试放进每次提交的检查流程,再单独安排需要凭据的真实契约测试。两者承担不同任务:前者验证应用对已定义响应的处理,后者核对真实服务是否仍符合这些假设。模拟通过,不应被解释为上游接口已经验证通过。
真实测试只检查结构、字段类型和必要能力,不固定自然语言答案。保存夹具前移除密钥、用户内容和敏感工具参数,并记录采集日期、接口类型及客户端版本。接口或 SDK 升级时,先对照契约更新夹具,再运行完整故障矩阵。
现在就到 CodeRelay Hub 开通免费工作区。