FileFixtures Strategy
The FileFixturesStrategy is a template-based strategy that uses Jinja2 templates to generate responses. It's particularly useful for creating consistent mock responses for your API endpoints.
Overview
This strategy:
- Uses Jinja2 templates stored in a specified directory
- Intelligently matches requests to templates based on the request path
- Supports the GET, POST, PUT, PATCH and DELETE HTTP methods; HEAD and OPTIONS requests are answered 405 Method Not Allowed
- Simulates resource creation for POST requests that match no template (behavior controlled via configuration)
- Provides OpenTelemetry integration for observability
Template Resolution
For a given request path like /api/v1/projects/1234, the strategy will look for templates in the following order:
api-v1-projects.1234.j2(specific to the resource ID)api-v1-projects.j2(generic for the resource type)index.j2(fallback template)
A path segment counts as an identifier when it looks like one: a UUID (with or without
dashes), or an even-length string of digits or hexadecimal characters. With several
identifiers the most specific name comes first: /api/v1/projects/1234/tasks/abcd tries
api-v1-projects-tasks.1234.abcd.j2, then api-v1-projects-tasks.1234.j2,
api-v1-projects-tasks.j2 and index.j2.
A rendered template is served with the request's Content-Type, or application/json
when the request has none.
HTTP Method Handling
GET Requests
- Attempts to find and render a matching template
- Returns 404 if no matching template is found
POST Requests
The strategy intelligently handles POST requests based on the request context:
- Templates: With
filefixtures_enable_templates_for_postenabled (the default), a matching template is looked up first, as for a GET, and rendered with a 200 - Search Requests: If the path looks like a search (it ends in
_search,/search,_queryor/query), returns a template response - Command Requests: If the path looks like a command (it ends in
_command,/command,_cmd,/cmd,_run,/run,_executeor/execute), returns a 201 CREATED status with template response - Resource Creation: Otherwise, simulates resource creation with injected metadata, when
filefixtures_simulate_create_on_missingis enabled (the default). When it is disabled, a create-looking POST with no matching template gets the same 404 missing-resource response as a GET with no template, instead of a simulated create.
With templates for POST enabled, step 1 has already looked for the template, so a search or
command POST is answered 200 by its template, or 404 when there is none. Since index.j2
matches every path, a templates directory containing an index.j2 answers every POST from it,
create-looking ones included; set filefixtures_enable_templates_for_post=False to restore the
search (200), command (201) and create handling.
DELETE/PUT/PATCH Requests
- Returns 204 NO CONTENT by default
- These are no-op operations in the default implementation
Template Context
Templates have access to the following context variables:
query: The query parameters, as a dictheaders: The request headers, as a dict (names lower-cased)request_json: The parsed JSON body of a POST request with a JSON content type (application/jsonortext/json) or a path ending in.json; otherwiseNone- Identifiers inferred from the path: each ID-like segment is available under the name of the segment before it (
projectsfor/api/v1/projects/<uuid>), or asidwhen nothing comes before it
Resource Creation
When simulating resource creation (POST requests), the strategy injects the following metadata fields by default:
{
"id": "{{ uuid4() }}",
"createdAt": "{{ utcnow().isoformat() }}",
"updatedAt": "{{ utcnow().isoformat() }}",
"createdBy": "{{ request.headers.get('X-User-Id', uuid4()) }}",
"status": {
"code": "OK",
"error_code": null
}
}
The response is a 201 CREATED echoing the request's JSON body with these fields rendered into
it; the field templates can use uuid4(), utcnow() and request. A POST that is not JSON (see
request_json above) gets a 201 with an empty body. The fields are set with
created_resource_metadata.
Configuration
The strategy requires the following configuration:
settings = Settings(
strategy="filefixtures",
templates_dir="/path/to/templates",
filefixtures_enable_templates_for_post=True, # Optional: Enables template-based responses for POST requests
filefixtures_simulate_create_on_missing=False, # Optional: Disables the create-simulation fallback for POSTs without a template
)
Example Template
Here's an example template for a user resource, api-v1-users.j2, which serves
GET /api/v1/users/<uuid>:
{
"id": {{ users | tojson }},
"name": "Test user",
"fields": {{ query.get("fields", "all") | tojson }}
}
OpenTelemetry Integration
With tracing on (see OpenTelemetry settings,
which need the opentelemetry extra), the strategy adds the following attributes to the
request's span:
mockstack.filefixtures.template_name: The name of the template being rendered
Error Handling
When no matching template is found, the strategy returns a 404 response with the following structure. The exception is a POST that looks like resource creation: with filefixtures_simulate_create_on_missing enabled (the default), a missing template there falls back to simulating creation (see Resource Creation) instead of 404ing. Set filefixtures_simulate_create_on_missing=False to turn that fallback off and get the same 404 as any other unmatched request.