In several situations where the software we developed interfaces some kind of REST based third party API that was not available during development. The interactions may be as simple as a service that more or less returns a simple document like a user list or as complicated as a workflow interaction, where the service results correlate somewhat with the call.
Probably the most obvious way to solve this is to provide some kind of mock that mimics the behavior of the actual service being called. These mocks often are some kind of dumping ground, because noone feels responsible for it (hey - it's actually what the third party does ;P). The code inside is mostly very simple, since it just implements a facade, which is just good enough, so that the system you are developing feels that everything needed is there.
Basic Concept
WireMock.Net allows to match requests to responsible responders by defining criteria for:
- HTTP verb
- URI
- request headers
- request body
A responder may either return a static or even dynamic result specifying:
- status code
- response headers
- reponse body
Configuring
Configuration can happen via JSON files or a REST API, both of which are valuable options. The syntax used in both is identical, configuration via rest means uploading files with the same content as when using configuration files. There is just one thing to be careful about:
Make sure to use unique GUIDs, otherwise you will overwrite previous definitions.
Files
Files configuration is what I chose in my project at work. Here we want the mock to stick around for a long time and changes to the configuration are seldom and infrequent. We host WireMock inside IIS for the sake of convenience. A mappings json file defines matching rules for HTTP requests. This is very similar to what a route map looks like in ASP.NET MVC or express.js. Rules can apply to url, HTTP method, headers and body. For instance to map to a specific URL, an ExactMatcher can be used:
"Request": {
"Path": {
"Matchers": [
{
"Name": "ExactMatcher",
"Pattern": "/V1/api/ShoppingCart"
}
]
},
}
Exact matching won't be that useful for all rules, especially, if you peek into the request body. There are many more matchers, e.g. to evaluate XPath expressions, peek into JSON documents or evaluate C# expressions. The response for a matched request can either be defined inline or in a referenced file:
"Response": {
"StatusCode": 200,
"BodyAsFile": "shopping_cart.json",
"UseTransformer": false,
"Headers": {
"Content-Type": "application/json; charset=utf-8",
"api-supported-versions": "1.0"
}
}
Responses do not have to be static, you can use templating to project values from the request into the response or dynamically calculate the name of the file to return. Handlebars and Scriban are supported as engines.
"Response": {
"Headers": { "Content-Type": "application/xml" },
"BodyAsFile": "c:\\temp-wiremock\\__admin\\mappings\\_{{request.query.MyUniqueNumber}}_\\MyXmlResponse.xml",
"UseTransformer": true
}
To be able to template against a JSON request payload, there is even a helper function to use in templating to navigate JSON documents. All in all there is a lot you can do, but the learning curve is absolutely flat.
API
The API defines several endpoints to upload/download settings/files. All in all this is pretty self explanatory. I guess the main usecase for using the API is integrative unit testing, where you want to configure the mock with new routes, when a new test starts.
Hosting
There are multiple hosting options. You may host WireMock inside IIS, run it as a dotnet tool or self host it in your process.
IIS
I was unaware, how easy it would be to host this in IIS. I just had to include a web.config like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="dotnet-wiremock.exe" arguments="--Port 80 --ReadStaticMappings true" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>
</configuration>
To have access to the tools assemblies, I had to copy them to the directory of the web application:
- dotnet-wiremock.exe went into the root folder
- The .store folder and related subfolders went into the root follder
- In addition I put the mappings.json file (and additional response files) into __admin\mapping.
Dotnet Tool
dotnet-wiremock.exe can just be run from the commandline and serves HTTP until being actively terminated. This is the easiest way to start off and configure or test matchers.
Self Hosted
WireMock can be spun up in a process by using it as a library. This is probably the smoothest integration for integrative unit tests.
Final Thoughts
With the experience I had so far with it, I would always try to stick to tools like this for your HTTP mocking needs if at all possible. Custom developed applications in my experience seem to be a dumping ground of bad code, which does not get any care or maintenance. Configuration based mocking with powerful tools like dynamic matchers allows to create configurable artifacts that can be checked in along with the regular code. Configuration is trivial if you have a solid knowledge of HTTP. When some reasonable rules have been created, even non-developers will be able to extend the configuration.
Cheers!!!
Top comments (1)
Nice blog ;-)