测试插件
字数
757 字
阅读时间
3 分钟
TIP
测试验证的是行为,而不是复述实现。推荐的风格是「组装真实的部件,只替换最外层的边界」:数据库和会话存储用内存实现,模型用假提供商,其余链路都跑真实代码。
先跑起来
bash
yarn build
yarn test不先构建,新包会报找不到模块,因为产物是按包生成的,构建前并不存在。
最小测试
ts
const ctx = new Context()
ctx.plugin(SessionService, { store: new MemorySessionStore() })
ctx.plugin(AIService)
ctx.plugin(MyPlugin)
const result = await ctx.chatluna.ask({ prompt: 'hi' })- 每个测试新建一个上下文。
- 只加载待测插件和它真正依赖的服务。
- 测试结束后释放上下文,避免定时器和监听器泄漏。
假模型与假时间
单元测试用 mock 提供商代替真实模型:输出固定、便于断言,可以主动注入错误,也不产生网络请求和费用。测试流式输出时,可以让它按分片返回。
定时任务、超时和退避重试等逻辑,用测试框架的可控时钟,不要真的等待,否则既慢又不稳定。
断言什么
- 行为:给定输入后,输出、派发的事件或日志是否符合预期。
- 边界:失败时返回什么错误,有没有残留不一致的中间状态。
- 生命周期:卸载后监听器是否注销、定时器是否清理。
不要断言私有的实现细节,否则每次重构都要改测试。
集成测试
验证多个服务协作时写集成测试,例如:消息从接收到投递的完整链路、带权限校验的工具调用是否被正确拦截、定时任务触发的一次会话唤醒。每个测试只验证一条核心链路。
常见陷阱
- 共享上下文:测试之间复用上下文会互相干扰。
- 没等异步收尾:事件通常并行广播,断言前要等异步队列清空。
- 依赖执行顺序:换个顺序就失败,说明用例之间有隐式依赖。
- 请求真实网络:单测中不要连外网,始终用假提供商。
调试
- 开启 trace,按 span 逐层检查每一步。
- 用
ctx.logger输出关键状态,不要到处散落console.log。 - 失败时先看断言前的最后一条事件,而不是通读全部日志。
提交前
- 相关测试全部通过。
- 新增或变更的行为都有测试覆盖。
- 没有引入无关的临时依赖或构建产物。