Integration Testing
Switch mock scenarios from your test suite using the X-Mock-Scenario header — no dashboard changes, full parallelization
Integration Testing
Your test suite can tell Mock Alpha which scenario to serve for each request. This lets you test multiple code paths (error handling, retries, timeouts) without touching the dashboard or restarting the server.
The pattern is stateless: each request declares its scenario independently, so parallel tests never collide and test failures leave no dirty state behind.
Scenario resolution order
When a request arrives, Mock Alpha picks a scenario in this order:
- Session override — if the request sends
X-Mock-Sessionand you have an active override for that session in the dashboard X-Mock-Scenarioheader — the scenario key to serve?scenario=query parameter — the scenario key in the URL- Match rules — if no explicit key is set, rules are evaluated in priority order
- Default scenario — if no rule matches, the scenario marked as default (or the first one if none is marked)
An explicit key wins, but only if it exists. If you send
X-Mock-Scenarioor?scenario=and that key matches a scenario on the endpoint, match rules are skipped. If the key does not match any scenario on the endpoint, resolution falls through to match rules and then the default — so a typo'd or removed scenario key behaves as if no key were sent at all, not as an error. Remove the header while testing rule-based logic.
Android (Kotlin)
Use an interceptor to inject the header before each test, choosing the scenario per test:
// Test build only — one interceptor per test, scenario chosen per test
class MockScenarioInterceptor : Interceptor {
@Volatile var scenario: String? = null
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder()
.header("X-Api-Key", BuildConfig.MOCK_ALPHA_KEY)
.apply { scenario?.let { header("X-Mock-Scenario", it) } }
.build()
return chain.proceed(request)
}
}
@Before fun setUp() { interceptor.scenario = null }
@Test fun `shows retry banner when the server fails`() {
interceptor.scenario = "error_500"
// ...assert the UI shows the retry banner
}
@Test fun `navigates to home after login succeeds`() {
interceptor.scenario = "success"
// ...assert navigation
}iOS (Swift)
Rebuild the session when the scenario changes:
// Test target only — rebuild the session when the scenario changes
enum MockScenario {
static func session(_ scenario: String?) -> URLSession {
let config = URLSessionConfiguration.ephemeral
var headers = ["X-Api-Key": mockAlphaKey]
if let scenario { headers["X-Mock-Scenario"] = scenario }
config.httpAdditionalHeaders = headers
return URLSession(configuration: config)
}
}
func testShowsRetryBannerOnServerError() async throws {
let client = ApiClient(session: MockScenario.session("error_500"))
// ...assert the view model surfaces the retry state
}
func testNavigatesToHomeAfterLoginSucceeds() async throws {
let client = ApiClient(session: MockScenario.session("success"))
// ...assert navigation
}Common scenario keys
Mock Alpha doesn't ship any scenarios by default — every scenario on every endpoint is one you (or an AI agent) create. These keys are just a naming convention the dashboard recognizes for coloring and labeling; using them is optional but makes scenarios easier to scan at a glance:
| Key | Description | Use in tests |
|---|---|---|
success | Successful response (2xx) | Happy path, normal flow |
error_401 | Unauthorized — invalid or missing token | Token expiry, permission denied |
error_500 | Server error — temporary fault | Retry logic, error UI |
timeout | Slow response — pair with delayMs scenario config | Timeout handling, spinners |
Create scenarios (with any key you like) in the dashboard's Endpoint page, then reference them in tests by name.
Why headers instead of session override
The dashboard's session override is powerful for manual exploration but not for test suites:
| Aspect | Header (test suites) | Session override (dashboard) |
|---|---|---|
| Stateless per request | ✓ Yes | ✗ Global state |
| Parallel tests safe | ✓ Yes | ✗ Tests collide |
| Survives test failure | ✓ Yes | ✗ Leaves dirty state |
| Scope | Per request | Per X-Mock-Session session |
The header approach means a test failure leaves nothing behind — the next test starts clean.
Request body in assertions
Some tests need to verify that the mock served the right scenario. Every response includes the scenario key:
let response = try await client.fetch(...)
let scenarioUsed = response.headers["X-Mock-Scenario"] ?? "default"
XCTAssertEqual(scenarioUsed, "error_401")Authoring new scenarios
Once you design a test flow, you'll likely need new scenarios (error codes, edge cases) that don't exist yet on the endpoint.
The fastest way is to use the AI agent to author scenarios conversationally. For example:
"For the
/payments/chargeendpoint, add a scenario where the card is declined. The response should be a 400 with a message 'Card declined' and an error code 'insufficient_funds'."
The agent writes the scenario to the dashboard, and your next test run picks it up immediately.