Mock chat model with fakeModel
fakeModel is a builder-style fake chat model that lets you script exact responses (text, tool calls, errors) and assert what the model received. It extends BaseChatModel, so it works anywhere a real model is expected.
Quick start
Create a model, queue responses with.respond(), and invoke. Each invoke() consumes the next queued response in order:
Tool calling responses
.respond() supports tool calls by passing an AIMessage with tool_calls:
.respondWithTools() is a shorthand for the same thing. Instead of constructing the full AIMessage, provide just the tool name and arguments:
id field is optional. If omitted, a unique ID is auto-generated.
Simulate errors
Errors at specific turns
Passing anError to .respond() makes the model throw on that specific invocation. Errors can appear at any position in the sequence:
Errors on every call
.alwaysThrow() makes every invocation throw, regardless of the queue. This is useful for testing error handling and retry logic:
Dynamic responses with factory functions
.respond() also accepts a function that computes the response based on the input messages. The function receives the full message array and returns either a BaseMessage or an Error:
Each function is a single queue entry, consumed once. To reuse the same dynamic logic for multiple turns, queue multiple
respond function calls.Structured output
For code that uses.withStructuredOutput(), configure the fake return value with .structuredResponse():
.withStructuredOutput() is ignored. The model always returns the value configured with .structuredResponse(). This keeps tests focused on application logic rather than parsing.
Assert what the model received
fakeModel records every invocation, including the messages and options passed to the model. This works like a spy or mock in traditional testing frameworks:
Use with bindTools
Agent frameworks like LangChain agents and LangGraph call model.bindTools(tools) internally. fakeModel handles this automatically. The bound model shares the same response queue and call recording as the original, so no special setup is needed:
Full example: test a tool-calling agent with vitest
Full example: test a tool-calling agent with vitest
Next steps
Learn how to test your agent with real model provider APIs in Integration testing.Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

