Skip to main content
集成测试用于验证您的智能体能否与模型 API 和外部服务正确协同工作。与使用模拟和桩的单元测试不同,集成测试会进行实际的网络调用,以确认组件能协同工作、凭证有效且延迟在可接受范围内。 由于 LLM 的响应具有不确定性,集成测试需要采用与传统软件测试不同的策略。本指南将介绍如何为您的智能体组织、编写和运行集成测试。关于为 LangChain 本身贡献代码时的一般测试基础设施,请参阅代码贡献指南

分离单元测试和集成测试

集成测试速度较慢且需要 API 凭证,因此请将其与单元测试分开。这样您可以在每次更改时运行快速的单元测试,而将集成测试保留给 CI 或部署前检查。 使用文件命名约定来分离集成测试。将集成测试文件命名为 *.int.test.ts,并配置 vitest 在默认运行中排除它们:
vitest.config.ts
package.json 中添加脚本:
显式运行集成测试:

管理 API 密钥

集成测试需要真实的 API 凭证。请从环境变量中加载它们,以确保密钥不会进入源代码管理。 dotenv/config 添加为 vitest 的 setup 文件,以便环境变量能自动从 .env 加载:
vitest.config.ts
.env
当密钥缺失时跳过测试:
.env 添加到您的 .gitignore 文件中,以避免提交凭证。在 CI 中,通过您提供商(例如 GitHub Actions secrets)的密钥管理功能注入密钥。

断言结构,而非内容

LLM 的响应在不同运行之间会有所变化。与其断言确切的输出字符串,不如验证响应的结构属性:消息类型、工具调用名称、参数形状和消息数量。
此示例使用了自定义测试匹配器。有关设置和完整的匹配器参考,请参阅下文。
要进行更严格的轨迹断言,请使用 AgentEvals 评估器,它支持 unorderedsuperset 等模糊匹配模式。

使用自定义测试匹配器

langchain 提供了自定义的 vitest 匹配器,使结构断言更具可读性,并在失败时产生清晰的错误信息。在 setup 文件中注册一次,它们就可以在每次 expect() 调用中使用。

设置

添加一个 vitest setup 文件,用 LangChain 匹配器扩展 expect
vitest.setup.ts
在您的 vitest 配置中引用它:
vitest.config.ts
TypeScript 类型已自动包含,因此无需额外配置即可获得自动补全。

检查消息类型

每个消息类都有一个对应的匹配器:toBeHumanMessage()toBeAIMessage()toBeSystemMessage()toBeToolMessage()。不带参数调用仅检查类型,或传递字符串以同时匹配内容:
传递一个对象以匹配特定字段:

断言工具调用

有三个匹配器用于处理 AIMessage 上的工具调用断言:

断言工具消息

toHaveToolMessages() 接收完整的消息数组,并按顺序检查其中的 ToolMessage 实例:

断言中断和结构化响应

toHaveBeenInterrupted() 检查 LangGraph 中断 结果中是否存在 __interrupt__ 字段。传递一个值以匹配中断负载:
toHaveStructuredResponse() 检查结果上是否存在 structuredResponse 字段。传递一个对象以匹配特定字段:

匹配器参考

降低成本和延迟

调用 LLM API 的集成测试会产生实际成本。以下几种做法有助于保持测试套件的快速和负担得起:
  • 使用较小的模型:对于仅需验证工具调用和响应结构的测试,使用 gemini-3.1-flash-lite-preview 或等效模型。
  • 设置 maxTokens:限制响应长度,避免冗长且昂贵的补全。
  • 限制测试范围:每个测试只测试一种行为。当单轮测试足够时,避免使用需要多次 LLM 调用的端到端场景。
  • 选择性运行:利用上文的测试分离,仅在 CI 或部署前运行集成测试,而不是每次保存文件时都运行。

后续步骤

了解如何使用确定性匹配或 LLM-as-judge 评估器在 Evals 中评估智能体轨迹。