测试策略:真实逻辑优先
测试策略:真实逻辑优先
学习目标
本章聚焦 LibreChat 的测试哲学。你将了解:
- 为什么优先使用真实依赖而非 Mock
- Spy 与 Mock 的选择策略
- MongoDB 内存服务器 vs Mock DB
- MCP 真实 SDK 导出 vs 模拟
- 测试分层与集成测试的组织
前置知识
- Jest 测试框架基础
- 单元测试与集成测试的区别
项目实践
测试分层
LibreChat 的测试分为三层:
| 层次 | 工具 | 文件模式 | 覆盖范围 |
|---|---|---|---|
| 单元测试 | Jest | *.spec.ts | 单个函数/类的输入输出 |
| 集成测试 | Jest | *.integration.spec.ts | 多模块协作 |
| E2E | Playwright | e2e/specs/ | 完整用户流程 |
Mock 策略
LibreChat 的 Mock 优先级原则:
真实逻辑 > Spy > Mock > Stub
1. 优先使用真实依赖(MongoDB 内存服务器、真实 MCP SDK)2. 仅在无法控制的外部系统使用 Mock(HTTP API、系统调用)3. 用 Spy 验证调用参数和频率,不替换逻辑Spy 优于 Mock:
// ✅ Spy:保留原始逻辑,仅记录调用const spy = jest.spyOn(db, 'getConvoFiles');await initializeAgent(params, db);expect(spy).toHaveBeenCalledWith(conversationId);
// ❌ Mock:替换原始逻辑jest.spyOn(db, 'getConvoFiles').mockResolvedValue([]);Spy 的优势是:如果 getConvoFiles 的内部逻辑有 bug,Spy 仍然会执行它并暴露问题,而 Mock 会跳过。
MongoDB 内存服务器
import { MongoMemoryServer } from 'mongodb-memory-server';
const mongo = await MongoMemoryServer.create();const uri = mongo.getUri();// 使用真实 MongoDB 实例进行测试这比 Mock DB 调用更真实——实际的查询语法、索引约束、聚合管道都会被执行。如果 schema 验证有 bug,内存服务器会暴露出来,而 Mock 不会。
MCP 真实 SDK 导出
import { CallToolResultSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';测试中使用真实的 @modelcontextprotocol/sdk 导出,而非模拟 MCP 协议的行为。这确保了:
- 工具调用格式符合 MCP 规范
- 错误码使用标准值
- Schema 验证与实际一致
集成测试组织
集成测试文件使用 *.integration.spec.ts 命名约定,与普通单元测试区分。
典型集成测试场景:
capabilities.integration.spec.ts:中间件能力检查的完整流程bulk-parity.spec.ts:批量操作与单条操作的等价性验证
问题与规避
问题 1:内存 MongoDB 与生产 MongoDB 版本不一致
规避:mongodb-memory-server 可以指定 MongoDB 版本。CI 中使用的版本应与生产环境一致。开发环境可以使用最新版本以便快速启动。
问题 2:过度 Mock 导致测试通过但实际代码有 bug
规避:这是 LibreChat 选择”真实逻辑优先”的核心原因。减少 Mock 使用,增加 Spy 和真实依赖的比例。仅在测试不稳定的外部依赖(如 HTTP API)时使用 Mock。
问题 3:集成测试运行时间长
规避:集成测试在 CI 中并行运行。Jest 的 --testTimeout 配置给集成测试更长的超时时间。本地开发时可以仅运行单元测试快速反馈。
设计取舍
真实逻辑优先 vs 速度优先
| 方案 | 优势 | 代价 |
|---|---|---|
| 真实逻辑(LibreChat) | 高置信度、发现真实 bug | 测试运行慢、环境依赖 |
| 速度优先(大量 Mock) | 测试运行快、环境无关 | 测试通过但实际有 bug |
LibreChat 选择了真实逻辑优先,因为:
- 项目是 AI 应用,交互逻辑复杂,Mock 容易遗漏边界情况
- MongoDB 内存服务器启动仅需几秒,成本可接受
- E2E 测试已经覆盖了完整流程,单元测试应聚焦真实逻辑