Switching from openai-responses to aimock
openai-responses intercepts httpx calls to mock OpenAI responses inline. aimock runs a real HTTP server with fixture files—no monkey-patching, works with any framework, supports streaming.
Before / After
Side-by-side: mocking a chat completion with openai-responses vs. aimock.
import openai_responses
from openai import OpenAI
@openai_responses.mock()
def test_chat(openai_mock):
openai_mock.chat.completions.create.response = {
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Hello!"},
"finish_reason": "stop"
}]
}
client = OpenAI()
result = client.chat.completions.create(
model="gpt-4o", messages=[{"role": "user", "content": "hi"}]
)
assert result.choices[0].message.content == "Hello!"
from openai import OpenAI
def test_chat(aimock):
aimock.on_message("hi", {"content": "Hello!"})
client = OpenAI(base_url=aimock.url + "/v1", api_key="test")
result = client.chat.completions.create(
model="gpt-4o", messages=[{"role": "user", "content": "hi"}]
)
assert result.choices[0].message.content == "Hello!"
Or with fixture files:
{
"fixtures": [
{
"match": { "userMessage": "hi" },
"response": { "content": "Hello!" }
}
]
}
def test_chat(aimock):
aimock.load_fixtures("./fixtures/chat.json")
client = OpenAI(base_url=aimock.url + "/v1", api_key="test")
result = client.chat.completions.create(
model="gpt-4o", messages=[{"role": "user", "content": "hi"}]
)
assert result.choices[0].message.content == "Hello!"
Step-by-step migration
-
Install aimock-pytest (replaces
pip install openai-responses)pip install aimock-pytest -
Convert inline mock definitions to fixture files or
on_message()calls. Instead of constructing the full response envelope manually, just specifycontentortoolCalls—aimock generates the envelope automatically. -
Replace the decorator —
@openai_responses.mock()becomes theaimockpytest fixture parameter (auto-provided by aimock-pytest). -
Point the client at aimock — replace
OpenAI()withOpenAI(base_url=aimock.url + "/v1", api_key="test").
Feature mapping
| openai-responses | aimock |
|---|---|
@openai_responses.mock() decorator |
aimock pytest fixture (auto-provided) |
openai_mock.chat.completions.create.response = {...} |
aimock.on_message("pattern", {"content": "..."}) |
| Partial envelope (choices required, other fields auto-filled) |
Just specify content or toolCalls—envelope
auto-generated
|
openai_mock.chat.completions.create.route.calls |
aimock.journal |
| Python + OpenAI only | Python, TypeScript, any LLM provider |
Manual SSE chunk construction (streaming.EventStream) |
Automatic SSE streaming from fixture content |
| No fixture files | JSON fixture files with match patterns |
| httpx monkey-patching | Real HTTP server—works with any HTTP client |
| ✗ No record/replay |
npx -p @copilotkit/aimock llmock --record captures real API calls
|
| ✗ No CI action | CopilotKit/aimock@v1 GitHub Action |
| ✗ No chaos testing | Error injection, mid-stream disconnects |
What you gain
Cross-process, cross-language
Your Python tests, Node.js frontend, Go microservices, and Playwright E2E tests all hit the same mock server. No per-language patching.
Built-in SSE for 12 providers
OpenAI (Chat, Responses, Realtime), Claude, Gemini (REST, Live, and Interactions), Bedrock, Azure, Vertex AI, Ollama, Cohere. No manual chunk construction.
WebSocket APIs
OpenAI Realtime, Responses WS, Gemini Live. openai-responses cannot intercept WebSocket.
Record & Replay
Proxy real APIs, save as fixtures, replay forever.
npx -p @copilotkit/aimock llmock --record --provider-openai
https://api.openai.com
Fixture files
JSON files on disk. Version-controlled. Shared across tests. No hand-crafted envelopes.
Chaos testing
Inject latency, drop chunks, corrupt payloads mid-stream. Test your error handling under realistic failure conditions.
CI with GitHub Action
One step replaces all the httpx monkey-patching infrastructure in CI.
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Start aimock
uses: CopilotKit/aimock@v1
with:
fixtures: ./fixtures
- run: pip install -r requirements.txt
- run: pytest
env:
OPENAI_BASE_URL: http://127.0.0.1:4010/v1
OPENAI_API_KEY: mock-key
CLI / Docker quick start
npx -p @copilotkit/aimock llmock -p 4010 -f ./fixtures
docker run -d -p 4010:4010 \
-v $(pwd)/fixtures:/fixtures \
ghcr.io/copilotkit/aimock:latest \
-p 4010 -f /fixtures -h 0.0.0.0