useMockClient function
- bool shouldFail = false,
- int failStatusCode = 400,
- Object? responseFactory(
- Request request
- MockResponder? responder,
Configure all RestAPI instances to use an in-memory mock client.
Built on the public setClientFactory seam, so nothing in the core library references test scaffolding.
Call in test setup:
setUp(() => useMockClient()); // 200 + fake data
setUp(() => useMockClient(shouldFail: true, failStatusCode: 500));
A bare call restores generic successful fake responses and clears any prior responder; every other call replaces it with the explicitly configured per-request behavior.
Also usable for running the app against mock data in development:
// bootstrap.dart — Environment.useMocks is a compile-time constant, so
// this branch is tree-shaken out of release builds entirely.
if (Environment.useMocks) useMockClient();
By default every request resolves to FakeUtils.fakeJson, which is generic
and fine for exercising status handling. Supply responseFactory to return
app-shaped data keyed off the request:
useMockClient(responseFactory: (request) => switch (request.url.path) {
'/api/v1/products' => [ProductFake.fake().toJson(), ProductFake.fake().toJson()],
_ => ProductFake.fake().toJson(),
});
responseFactory can only ever produce a 200. When a test needs to vary
the status, set headers, or change its answer partway through, supply
responder — or assign bifrostMockResponder at any point afterwards:
useMockClient(responder: (request) async => http.Response('[]', 200));
// ...later, in one test:
bifrostMockResponder = (request) async => http.Response('denied', 403);
Responses are stamped with their request. MockClient populates
response.request from the response the handler returns, so it is null
unless the handler sets it — and clients that dereference
response.request! while parsing (PostgREST does, on both its success and
error paths) throw a null-check error instead of returning data. Since that
failure surfaces far from its cause, this fills the field in whenever a
responder left it empty.
Implementation
void useMockClient({
bool shouldFail = false,
int failStatusCode = 400,
Object? Function(http.Request request)? responseFactory,
MockResponder? responder,
}) {
final modes = <bool>[
shouldFail,
responseFactory != null,
responder != null,
].where((configured) => configured).length;
if (modes > 1) {
throw ArgumentError(
'Configure only one of shouldFail, responseFactory, or responder.',
);
}
if (responder != null) {
bifrostMockResponder = responder;
} else if (shouldFail || responseFactory != null) {
bifrostMockResponder = (request) => _defaultResponse(
request,
shouldFail: shouldFail,
failStatusCode: failStatusCode,
responseFactory: responseFactory,
);
} else {
bifrostMockResponder = null;
}
setClientFactory(
() => MockClient((request) async {
// Read the global per request rather than closing over `responder`, so a
// later assignment reaches a client an SDK has already captured.
final current = bifrostMockResponder;
final response = current != null
? await current(request)
: _defaultResponse(
request,
shouldFail: false,
failStatusCode: 400,
);
return response.request == null
? _withRequest(response, request)
: response;
}),
);
}