Skip to content

[Feature] 提供面向用户层单元测试的可脚本化 MockChatModel #1029

Description

@wucm667

Is your feature request related to a problem? Please describe.

eino 在 internal/mock/components/model/ChatModel_mock.go 有一份 mockgen 生成的 stub,但它在 internal/ 下,只供框架自身单测使用。

当用户为自己的 Agent / Graph 写单元测试时,没有一个官方、可脚本化、断言友好的 ChatModel 假体可用,只能:

  • 自己引 gomockEXPECT() setup
  • 或手写 struct 实现 model.BaseChatModel 接口

两种方式都有样板代码负担,且每个项目各写一套、不可移植。这直接影响「易维护」——测试难写,回归就难保障。

Describe the solution you'd like

新增包 components/model/modeltest,提供链式、可断言的假体:

m := modeltest.New().
    OnTurn(0).Reply("hello").
    OnTurn(1).ReplyToolCall("get_weather", `{"city":"sh"}`).
    OnTurn(2).Reply("18C").
    Build()

agent, _ := react.NewAgent(ctx, &react.AgentConfig{Model: m})
out, _ := agent.Generate(ctx, ...)

// 断言能力
require.Equal(t, "what's the weather", m.Calls()[0].LastUserMessage())
require.Equal(t, "get_weather", m.Calls()[1].LastToolMessageName())

要求:

  1. 同时实现 BaseChatModelToolCallingChatModel,可作为 react / ChatModelAgent 的 drop-in
  2. 支持 GenerateStream(脚本化流式分片)
  3. 支持 OnPrompt(matcher).Reply(...) 基于内容匹配的脚本
  4. 内置调用历史 Calls(),记录每次入参 messages / tools / options 便于断言
  5. 与现有 mockgen 生成的内部 mock 并存,用途不同(一个面向用户、一个面向框架内部)

不引入新外部依赖,不影响现有 ChatModel 实现。

Describe alternatives you've considered

  • 直接用 mockgen 的 ChatModel_mock.go:在 internal/ 下,对用户不可见;即便导出,gomockEXPECT() 写多轮对话脚本也很啰嗦。
  • 用户自写 struct 实现接口:每个项目重复,且没有统一的调用历史 / 断言能力。
  • 录制-回放真实模型响应:可作为后续增强(fixture from trace),但首版先做手写脚本,依赖更少。

Additional context

  • 竞品参考:Pydantic AI 的 TestModel / FunctionModel、Vercel AI SDK 5 的 MockLanguageModelV2、AutoGen 的 mock_response、LangChain 的 FakeChatModel
  • 包名 components/model/modeltestschema/modeltest 二选一可讨论。

愿意提交首版 PR。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions