A mocked response lets you test an SDK integration without spending tokens or depending on a live model. The useful target is your application’s behavior: the request it builds, the response it reads, and the failures it handles. This first lap uses Python, the OpenAI SDK, pytest, and HTTPX to exercise that path through the real SDK.
1. Put the SDK client behind an application function
Create a small function that accepts an SDK client and returns the text your application needs. For example, let generate_reply(client, model, prompt) call client.chat.completions.create, then extract choices[0].message.content. Passing the client into the function makes its network behavior replaceable during tests.
Keep the model identifier and credentials in configuration. For SwiftRelay, set the OpenAI SDK base URL to https://api.fastapirelay.com/v1. Include /v1 here because this walkthrough uses an OpenAI-compatible SDK. Use a dummy API key in mocked tests and keep real credentials out of fixtures.
2. Intercept HTTP requests with MockTransport
Install openai, httpx, and pytest in your test environment. Define an HTTPX request handler that accepts a request and returns an httpx.Response. Wrap it with httpx.MockTransport, pass that transport into httpx.Client, and supply that HTTP client through the OpenAI client’s http_client argument.
This arrangement exercises the SDK’s request serialization and response parsing. A directly stubbed application function would skip those boundaries. Create and close the client in a pytest fixture so each test starts with fresh state. Set max_retries=0 initially to make each expected request count explicit.
3. Build one realistic successful response
Have the handler return status 200 and a JSON chat completion object. Include id, object, created, model, and choices. Inside choices, include index, a message with role set to assistant and content set to a fixed sentence, and finish_reason set to stop. Add usage when your application reads token counts.
Use httpx.Response with its json argument to produce the JSON response. Then call your application function and assert that it returns the exact fixture sentence. Choose distinctive text, such as “The test shipment is ready,” so accidental hardcoded output is easier to spot.
4. Assert the outgoing request before returning data
Inside the handler, inspect the request before sending the fixture response. Assert that the method is POST and the URL path is /v1/chat/completions. Parse the request body as JSON and check the configured model identifier, message roles, and prompt content.
- Check the authorization header against the dummy key.
- Check optional parameters only when your application deliberately sets them.
- Compare parsed JSON values instead of serialized field order or whitespace.
These assertions catch configuration mistakes even when the mocked response looks correct. Avoid checking every SDK-generated header; doing so makes tests sensitive to changes that do not affect your application.
5. Exercise failures and retry behavior separately
Add fixtures for authentication failure, rate limiting, and a server error. Return appropriate HTTP status codes with an error object containing a message and type. Assert the behavior your application promises, such as raising a domain exception or displaying an actionable error message.
For a retry test, enable a bounded retry count and make the handler return a retryable error followed by success. Count requests and verify the final result. Control retry delays through the test setup so the test avoids real waiting. Simulate connection failures separately by raising an HTTPX connection exception from the handler.
6. Add fixtures for response shapes you actually consume
Test an empty choices array, null message content, and missing usage if your application needs to handle them. If you support tool calls or streaming, give each its own fixtures and assertions. A normal JSON completion does not exercise streamed event parsing or tool argument handling.
Run these cases locally and in continuous integration with dummy credentials. Keep fixture data small and free of customer prompts.
7. Confirm the boundary with one live smoke test
Mocks establish predictable application behavior; a live smoke test checks credentials, routing, and current model availability. SwiftRelay is a practical option for this final check because it works with OpenAI-compatible SDKs and bills per token. Sign up for SwiftRelay to use the small gift credit available to new accounts.
Keep the smoke test separate from the mocked suite, select a supported model identifier from your account, and send a short prompt. Assert that the response has the structure your application requires rather than expecting exact wording.