cloudwego / cloudwego/eino

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

Open
#1,029 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
13k
Forks
1.1k
Avg merge
4h 6m
Merged PRs (30d)
41

Description

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

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

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

- 自己引 `gomock` 写 `EXPECT()` setup
- 或手写 struct 实现 `model.BaseChatModel` 接口

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

### Describe the solution you'd like

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

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

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

### Describe alternatives you've considered

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

### Additional context

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

愿意提交首版 PR。

Contributor guide

Open the contributing guide

Research direction

Start by reading internal/mock/components/model/ChatModel_mock.go and the BaseChatModel and ToolCallingChatModel interfaces. Define the public components/model/modeltest package around the requested scripted turns, prompt matching, streaming, and call history. Done means it supports Generate and Stream as a drop-in model, exposes the stated assertions, adds coverage, introduces no external dependency, and preserves the existing internal mock.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
ai, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.