As promised, here's a PR that integrates my wiremock-snapshot extension. It adds a new API endpoint, /__admin/snapshot
, for recording stub mappings from the request journal. The README has more details, but here's a summary of the options it accepts:
"filters"
- Request patterns to use for determining the requests for which to create stub mappings.
- Possible values: Identical to
/__admin/requests/find
- Default: no filtering.
"persist"
- If set to true, persist stub mappings to disk. Otherwise, just output them.
- Possible values: true, false
- Default: true
"sortFields"
- Array of fields in the request to use for sorting stub mappings, mainly for output.
- Possible values: "url", "method", or a header name (e.g. "Accept")
- Default: no sorting.
"captureHeaders"
- Header matchers for including headers in the stub mapping. The request is matched against each matcher, and the associated header is added to the stub mapping if there's a match.
- Possible values: Request matchers for headers.
- Default: none
"outputFormat"
- Determines response body.
- Possible values: "ids" to return array of stub mapping IDs, "full" to return array of stub mapping objects
- Default: "ids"
Design issues
Filtering
Filtering is currently request-only. I'm not sure if response filtering is desired. If so, we'd probably want to add a new ResponsePattern
class (analogous to ResponsePattern
) to encapsulate matchers for the response. This would be best accompanied with some refactoring to make Response
into a an interface implemented by LoggedResponse
.
Body file extraction/naming
Currently, the API does not extract the response bodies to a separate file. While it'd be easy to add a flag to enable this, I think more granularity is needed. Body file extraction is useful for large binary responses, but generally undesirable for small JSON responses. Perhaps we can add a "bodyFileCritera"
option consisting of matchers that determine whether or not to extract the body. That way, you could use "headers": { "Content-Type": { "doesNotMatch": ".*json.*" } } }
to only extract non-JSON responses. Again, we'll probably want to add a ResponsePattern
class for this, and a "bodySize"
matcher to allow matching by the size of the body.
Uniqueness/Deduplication
To ensure stub mappings are unique, I have StubMappingTransformer#apply()
generate a MD5 hash of the RequestPattern
JSON and set that as the UUID. This is pretty hacky, but it seems to work well. I considered just using hashCode()
, but that's not appropriate since it has a high collision probability and the result is not guaranteed to be consistent between executions (see the JavaDoc).
This makes me wonder why StubMapping IDs are random instead of being a content-based hash. I see this was added in PR #306, but it doesn't seem uniqueness was considered.
Outputting
The options available in "outputFormat"
seem sufficient to me. If we add body file extraction, we may want to add another output format to serve everything in a zip file.
Sorting
I implemented the ability to sort the stub mappings by the request URL, method, or a header. The main use case for this is to make it easier to manually edit the stub mappings. This is arguably better served by extension points, so it might be better to just remove this feature.
The class used for sorting, RequestFieldsComparator
, is pretty hacky and a violation of the open-closed principle, but I couldn't think of a better implementation.
Extension points
An extension point for modifying StubMapping
objects would be easy to add. Specifically, we could have WireMockApp#buildAdminRequestHandler()
pass in the stub mapping extensions along with the API extensions to AdminRoutes
, which could then call
router.add(POST, "/snapshot", new SnapshotTask(this.stubMappingTransformerExtensions));
instead of
router.add(POST, "/snapshot", SnapshotTask.class);
Adding the ability to customize the file names for persisted mappings would be more complex. Perhaps we could use a wrapper class, e.g. RecordedStubMapping
, that would allow extensions to set the name for the mapping file and (if applicable) the body file.
Statefulness/Scenarios
It'd be easy to detect duplicate requests and then set the StubMapping
scenario name, but I'm not quite sure about naming. We could just use something like UniqueFilenameGenerator
to auto-generate the scenario name, but we'll probably want to have some way of customizing it. Maybe a "scenarioNameTemplate"
option that accepts a Handlebars template?
edit: Minor clarifications