部署和平台

🧪 测试策略

为 LangGraph.js 应用建立可回归的测试体系:单元测试、集成测试与端到端用例

📚 学习目标

学完这篇文章后,你将能够:

  • 为节点函数编写单元测试(不依赖网络/模型)
  • 为 Graph 编排编写集成测试(验证路由、分支与状态更新)
  • 为关键用户路径设计端到端用例(E2E 场景)
  • 识别哪些地方应该用 mock,哪些地方应该用真实依赖

前置知识

在开始学习之前,建议先阅读:

你需要了解:

  • 基本的测试框架用法(Vitest/Jest 任意一种)

1️⃣ 测试金字塔:先把钱花在最有效的层

一个务实的结论:

  • 80% 的回归问题,用 单元测试 + 少量集成测试 就能挡住
  • E2E 很贵,留给“最关键的路径”(支付/登录/核心对话)

2️⃣ 单元测试:把节点当成普通函数测

节点本质是 (state, config?) => Partial<State>,所以最好测。

import { describe, it, expect } from 'vitest';

type State = { input: string; output?: string };

async function uppercaseNode(state: State) {
  if (!state.input?.trim()) throw new Error('Input required');
  return { output: state.input.toUpperCase() };
}

describe('uppercaseNode', () => {
  it('uppercases input', async () => {
    const res = await uppercaseNode({ input: 'hello' });
    expect(res.output).toBe('HELLO');
  });

  it('rejects empty input', async () => {
    await expect(uppercaseNode({ input: '' })).rejects.toThrow('Input required');
  });
});

3️⃣ 集成测试:验证 Graph 的路由与状态合并

集成测试的目标不是“模型好不好”,而是:

  • 节点是否按预期执行
  • conditional edges 是否正确
  • reducer 是否正确合并
import { describe, it, expect } from 'vitest';
import { Annotation, StateGraph, START, END } from '@langchain/langgraph';

const StateAnn = Annotation.Root({
  n: Annotation<number>({
    reducer: (a, b) => a + b,
    default: () => 0,
  }),
  trace: Annotation<string[]>({
    reducer: (a, b) => a.concat(b),
    default: () => [],
  }),
});

const addOne = async (state: typeof StateAnn.State) => ({ n: 1, trace: ['addOne'] });
const addTwo = async (state: typeof StateAnn.State) => ({ n: 2, trace: ['addTwo'] });

describe('graph integration', () => {
  it('routes and reduces correctly', async () => {
    const app = new StateGraph(StateAnn)
      .addNode('a', addOne)
      .addNode('b', addTwo)
      .addEdge(START, 'a')
      .addEdge('a', 'b')
      .addEdge('b', END)
      .compile();

    const out = await app.invoke({});
    expect(out.n).toBe(3);
    expect(out.trace).toEqual(['addOne', 'addTwo']);
  });
});

4️⃣ E2E 用例:用最少数量覆盖“最关键路径”

对 AI 应用来说,E2E 不一定要断言“生成内容完全一致”,更建议断言:

  • 请求能成功(200)
  • 返回结构正确(例如 JSON/stream 格式符合协议)
  • 关键字段存在(引用、工具调用结果、错误码)

💡 练习题

  1. 单元测试:为你的“路由函数(shouldContinue)”写 3 条测试:有 tool_calls、无 tool_calls、异常输入。
  2. 集成测试:为你的 ReAct Loop 写一条测试:当工具返回结果时,必须回到 agent 节点再结束。
  3. E2E 设计:写出你项目的 2 条关键用户路径,并解释为什么它们值得用 E2E 覆盖。

📚 参考资源

官方文档


✅ 总结

本章要点

  • 节点是函数:优先写单元测试,成本最低、反馈最快。
  • Graph 编排要用集成测试覆盖(路由 + reducer + 顺序)。
  • E2E 留给关键路径,并用“结构断言”替代“内容一致断言”。

下一步:如果你在上线后遇到“慢/贵/不稳定”,回到《性能优化》从监控开始定位瓶颈。

登录以继续阅读

解锁完整文档、代码示例及更多高级功能。

立即登录

On this page