关于 effect-testing-mocking
面向 Effect 开发者的测试技能,介绍如何通过模拟服务和 Layer 编写确定性测试,并要求实现前先查阅本地 Effect 源码。
主要功能
- 01通过 Layer 模拟服务
- 02显式提供测试实现
- 03使用确定性测试时钟
- 04优先查阅本地 Effect 源码
适用场景
- 01在无外部 I/O 的情况下测试程序
- 02用模拟对象替换服务依赖
- 03确定性验证依赖时间的行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mepuka/ effect-ontology --skill effect-testing-mocking安装后在 Claude Code 中输入/effect-testing-mocking确认已加载。
详细介绍
测试与模拟
适用场景
- 需要不依赖外部 IO 的确定性测试
- 想通过层注入模拟服务
模拟层
const RepoTest = Layer.succeed(Repo, Repo.of({ find: () => Effect.succeed(mock) }))
提供测试实现
const result = yield* Effect.provide(program, RepoTest)
测试时钟
// Provide a deterministic Clock or use platform TestClock layer if available
指南
- 保持测试专注且快速;通过模拟服务避免网络请求
- 显式提供层,以满足程序要求
- 让测试贴近真实接口;不要为了测试而改造应用代码
- 使用
.Default层快速接线;为每个测试添加自定义模拟层 - 优先编写运行迅速、能快速失败的小型冒烟测试
常见问题
- 将真实 IO 泄漏到测试中 → 导致不稳定
- 过度模拟内部实现 → 导致测试脆弱;在服务边界进行模拟
交叉链接
- Layers & Services,了解 DI 模式
- Time/Logging,了解确定性时间和可观测输出
本地源码参考
重要:实现前先搜索本地 Effect 源码
完整的 Effect 源码位于 docs/effect-source/。编写 Effect 代码前,务必搜索实际实现。
关键源码文件
- Layer:
docs/effect-source/effect/src/Layer.ts - TestClock:
docs/effect-source/effect/src/TestClock.ts - TestContext:
docs/effect-source/effect/src/TestContext.ts
搜索示例
# Find Layer.succeed patterns for mocks
grep -F "Layer.succeed" docs/effect-source/effect/src/Layer.ts
# Study TestClock operations
grep -F "TestClock" docs/effect-source/effect/src/TestClock.ts
# Find test helpers
grep -F "TestContext" docs/effect-source/effect/src/TestContext.ts
# Look at Layer test examples
grep -F "Layer.succeed" docs/effect-source/effect/test/Layer.test.ts
工作流
- 确定所需的测试 API(例如 Layer.succeed、TestClock)
- 在
docs/effect-source/effect/src/Layer.ts中搜索实现 - 研究类型和测试模式
- 查看测试文件中的使用示例
- 根据实际实现编写代码
真实源码 > 文档 > 假设
实际示例:构建全面的测试层
export const TestLayer = (input?: TestLiveInput) =>
Effect.gen(function* () {
const tempDir = tempy.temporaryDirectory({ prefix: 'test' })
const cwd = (yield* setupFixtureFolder({ fixture: input?.fixture, tempDir })) ?? tempDir
const NodeOsTest = Layer.succeed(NodeOs, new NodeOs({ homedir: cwd, arch: 'arm64', platform: 'darwin' }))
const NodeProcessTest = Layer.succeed(NodeProcess, new NodeProcess({ cwd, platform: 'darwin', arch: 'arm64' }))
const ToolkitsRepoTest = Layer.succeed(ComposioToolkitsRepository, new ComposioToolkitsRepository({
getToolkits: () => Effect.succeed([]),
getToolsAsEnums: () => Effect.succeed([])
}))
const layers = Layer.mergeAll(
Console.setConsole(yield* MockConsole.effect),
CliConfig.layer(ComposioCliConfig),
NodeProcessTest,
Layer.provideMerge(ComposioUserContextLive, Layer.merge(BunFileSystem.layer, NodeOsTest)),
ToolkitsRepoTest,
EnvLangDetector.Default,
JsPackageManagerDetector.Default,
BunFileSystem.layer,
BunContext.layer,
MockTerminal.layer,
BunPath.layer
)
return layers
}).pipe(
Logger.withMinimumLogLevel(LogLevel.Debug),
Effect.scoped,
Layer.unwrapEffect,
Layer.provide(Layer.setConfigProvider(input?.baseConfigProvider ?? ConfigProvider.fromMap(new Map([]))))
)
参考资料
- Agent Skills 概览:https://www.anthropic.com/news/skills
- Skills 指南:https://docs.claude.com/en/docs/claude-code/skills
评论
支持 Markdown