-
-
Notifications
You must be signed in to change notification settings - Fork 211
Request Matching
WireMock.Net supports matching of requests to stubs and verification queries using the following parts:
- Path
- URL
- HTTP Method
- Query parameters
- Headers
- Cookies
- Request Body
Most matchers have 2 extra properties:
- IgnoreCase = define that the matcher should match ignoring the case
- RejectOnMatch = define that when the matcher does match successfully, this should be counted as a invalid (non-matching) match
server
.Given(Request
.Create()
.WithParam("search", "abc")
{
"Request": {
"Params": [
{
"Name": "search",
"Matchers": [
{
"Name": "ExactMatcher",
"Pattern": "abc"
}
]
}
]
}
}
// todo
{
"Request": {
"Headers": [
{
"Name": "api-key",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "abc*"
"IgnoreCase": true
}
]
}
]
}
}
Note that when you want to match on a missing header, you need to use this mapping:
{
"Request": {
"Headers": [
{
"Name": "api-key",
"IgnoreCase": true,
"RejectOnMatch": true
}
]
}
This means that when the header-key api-key
(ignoring the casing) is missing the header mapping will match because RejectOnMatch
is true
.
The following paragraphs describe in detail which matchers can be used.
At this moment these matchers are supported:
- ExactMatcher
- LinqMatcher
- CSharpCodeMatcher
- GraphQLMatcher
- JsonMatcher
- JsonPartialMatcher
- JsonPartialWildcardMatcher
- JsonPathMatcher
- JmesPathMatcher
- MimePartMatcher
- XPathMatcher
- RegexMatcher
- SimMetricsMatcher
- WildcardMatcher
- ContentTypeMatcher(🚧)
- NotNullOrEmptyMatcher
- CustomMatcher
Can be used to exactly match a string or object.
var server = WireMockServer.Start();
server
.Given(Request.Create().WithPath("/exact")
.WithParam("from", new ExactMatcher("abc")))
.RespondWith(Response.Create()
.WithBody("Exact match")
);
{
"Guid": "67ae335b-5d79-42dc-8ca7-236280ab9111",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/exact"
}
]
},
"Params": [
{
"Name": "from",
"Matchers": [
{
"Name": "ExactMatcher",
"Pattern": "abc"
}
]
}
]
},
"Response": {
"Body": "Exact match"
}
}
Can be used to match an object using Dynamic Linq (https://github.com/StefH/System.Linq.Dynamic.Core)
var server = WireMockServer.Start();
server
.Given(Request.Create().WithPath("/linq")
.WithParam("from", new LinqMatcher("DateTime.Parse(it) > \"2018-03-01 00:00:00\"")))
.RespondWith(Response.Create()
.WithBody("linq match !!!")
);
{
"Guid": "67ae335b-5d79-42dc-8ca7-236280ab91ec",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/linq"
}
]
},
"Params": [
{
"Name": "from",
"Matchers": [
{
"Name": "LinqMatcher",
"Pattern": "DateTime.Parse(it) > \"2018-03-01 00:00:00\""
}
]
}
],
"Body": {}
},
"Response": {
"Body": "linq match !!!"
}
}
Advanced! With this matcher you can use complex C# code to match an JObject or string value.
- You need to include the NuGet package WireMock.Net.Matchers.CSharpCode
- Note that this functionality will only work if enabled in the settings (
AllowCSharpCodeMatcher = true
). - The argument-name from the string or JObject to match will be
it
.
var server = WireMockServer.Start();
server
.Given(Request.Create().WithPath("/cs")
.WithParam("from", new CSharpCodeMatcher("return it == \"x\";")))
.RespondWith(Response.Create()
.WithBody("cs match")
);
{
"Guid": "67ae335b-5d79-42dc-8ca7-236280ab9211",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/cs"
}
]
},
"Params": [
{
"Name": "from",
"Matchers": [
{
"Name": "CSharpCodeMatcher",
"Pattern": "return it == \"x\";"
}
]
}
],
"Body": {}
},
"Response": {
"Body": "cs match"
}
}
Can be used to match a GraphQL Query or Mutation using GraphQAL Schema.
var TestSchema = @"
input MessageInput {
content: String
author: String
}
type Message {
id: ID!
content: String
author: String
}
type Mutation {
createMessage(input: MessageInput): Message
updateMessage(id: ID!, input: MessageInput): Message
}
type Query {
greeting:String
students:[Student]
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}";
var server = WireMockServer.Start();
server
.Given(Request.Create()
.WithPath("/graphql")
.UsingPost()
.WithGraphQLSchema(TestSchema)
)
.RespondWith(Response.Create()
.WithBody("GraphQL is ok")
);
{
"Guid": "5a36d1c1-11df-4976-90f9-22cae5dadb38",
"UpdatedAt": "2023-07-08T17:02:06.1072879Z",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/graphql",
"IgnoreCase": false
}
]
},
"Methods": [
"POST"
],
"Body": {
"Matcher": {
"Name": "GraphQLMatcher",
"Pattern": "\r\n input MessageInput {\r\n content: String\r\n author: String\r\n }\r\n\r\n type Message {\r\n id: ID!\r\n content: String\r\n author: String\r\n }\r\n\r\n type Mutation {\r\n createMessage(input: MessageInput): Message\r\n updateMessage(id: ID!, input: MessageInput): Message\r\n }\r\n\r\n type Query {\r\n greeting:String\r\n students:[Student]\r\n studentById(id:ID!):Student\r\n }\r\n\r\n type Student {\r\n id:ID!\r\n firstName:String\r\n lastName:String\r\n fullName:String \r\n }"
}
}
}
}
Advanced! With this matcher you can use complex C# code to match an JObject or string value.
- You need to include the NuGet package WireMock.Net.Matchers.CSharpCode
- Note that this functionality will only work if enabled in the settings (
AllowCSharpCodeMatcher = true
). - The argument-name from the string or JObject to match will be
it
.
var server = WireMockServer.Start();
server
.Given(Request.Create().WithPath("/cs")
.WithParam("from", new CSharpCodeMatcher("return it == \"x\";")))
.RespondWith(Response.Create()
.WithBody("cs match")
);
The JMESPath language is described in an ABNF grammar with a complete specification. A JSON body will be considered to match a path expression if the expression returns either a non-null single value (string, integer etc.), or a non-empty object or array.
var server = WireMockServer.Start();
server
.Given(
Request.Create().WithPath("/jmespath_example").UsingGet()
.WithBody(new JmesPathMatcher("things.name == 'RequiredThing"));
)
.RespondWith(Response.Create().WithBody("Hello"));
{
"Guid": "55a600b8-9d6f-453f-90c6-3db2b0885ddb",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/jmespath_example",
"IgnoreCase": false
}
]
},
"Methods": [
"put"
],
"Body": {
"Matcher": {
"Name": "JmesPathMatcher",
"Pattern": "things.name == 'RequiredThing'"
}
}
},
"Response": {
"StatusCode": 200,
"Body": "{ \"result\": \"JmesPathMatcher !!!\"}",
"UseTransformer": false
}
}
// matching
{ "things": { "name": "RequiredThing" } }
{ "things": [ { "name": "RequiredThing" }, { "name": "Wiremock" } ] }
// not matching
{ "price": 15 }
{ "things": { "name": "Wiremock" } }
Deems a match if the attribute value is valid XML and matches the XPath expression supplied. An XML document will be considered to match if any elements are returned by the XPath evaluation. WireMock delegates to XPath2.Net, therefore it support up to XPath version 2.0.
var server = WireMockServer.Start();
server
.Given(Request.Create()
.WithPath("/xpath").UsingPost()
.WithBody(new XPathMatcher("/todo-list[count(todo-item) = 3]"))
)
.RespondWith(Response.Create().WithBody("XPathMatcher!"));
{
"Guid": "abc5848e-cedd-42ad-8f58-4ba6df01180f",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/xpath",
"IgnoreCase": false
}
]
},
"Methods": [
"post"
],
"Body": {
"Matcher": {
"Name": "XPathMatcher",
"Pattern": "/todo-list[count(todo-item) = 3]"
}
}
},
"Response": {
"StatusCode": 200,
"BodyDestination": "SameAsSource",
"Body": "XPathMatcher!",
"UseTransformer": false
}
}
Will match xml below:
<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>
The RegexMatcher can be used to match using a regular expression.
var server = WireMockServer.Start();
server
.Given(
Request.Create().WithPath("/reg").UsingPost()
.WithBody(new RegexMatcher("H.*o"));
)
.RespondWith(Response.Create().WithBody("Hello matched with RegexMatcher"));
// matching
Hello World
// not matching
Hi WM
SimMetrics.Net is used as a Similarity Metric Library, e.g. from edit distance's (Levenshtein, Gotoh, Jaro etc) to other metrics, (e.g Soundex, Chapman).
var server = WireMockServer.Start();
server
.Given(
Request.Create().WithPath("/reg").UsingGet()
.WithBody(new SimMetricsMatcher("The cat walks in the street."));
)
.RespondWith(Response.Create().WithBody("Matched with SimMetricsMatcher"));
// matching with distance 0.793
The car drives in the street.
// matching with distance 0.071
Hello
WildcardMatching is mostly used for Path and Url matching. This matcher allows a ? for a single character and * for any characters.
var server = WireMockServer.Start();
server
.Given(Request.Create().WithPath("/some*").UsingGet())
.RespondWith(Response.Create().WithBody("Hello"));
var server = FluentMockServer.Start();
server
.Given(
Request.Create().WithPath("/wc").UsingGet()
.WithBody(new WildcardMatcher("x."));
)
.RespondWith(Response.Create().WithBody("Matched with *"));
NotNullOrEmptyMatcher is used for Body matching. This matcher will return a match of the body is not null (BodyAsBytes, BodyAsJson, BodyAsString) or empty (BodyAsBytes, BodyAsString).
It's also possible to use a custom mapper with your own name.
{
"Guid": "67ae335b-5d79-42dc-8ca7-236280ab9211",
"Priority": 0,
"Request": {
"Path": {
"Matchers": [
{
"Name": "MyCustomMatcher",
"Pattern": "abc"
}
]
}
"Body": {}
},
"Response": {
"Body": "custom match"
}
}
The default behaviour for Matchers is MatchBehaviour.AcceptOnMatch so that when the matcher processes a request that corresponds with the matcher, the stubbed response is returned. In some scenarios you might want to reverse this behaviour so that the stubbed response is returned with the absence of a match.
e.g. You want to return 401 Unauthorised
if the caller does not provide a header containing the API Key:
server
.Given(Request.Create()
.WithPath("/needs-a-key")
.UsingGet()
.WithHeader("api-key", "*", MatchBehaviour.RejectOnMatch)
.UsingAnyMethod())
.RespondWith(Response.Create()
.WithStatusCode(HttpStatusCode.Unauthorized)
.WithBody(@"{ ""result"": ""api-key missing""}"));
A JSON Mapping example looks like:
{
"Guid": "29971ff8-4adb-4ec7-8b7d-a2ce6e5ca630",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/needs-a-key"
}
]
},
"Headers": [
{
"Name": "api-key",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "*",
"IgnoreCase": true,
"RejectOnMatch": true
}
]
}
]
},
"Response": {
"StatusCode": 401,
"BodyDestination": "SameAsSource",
"Body": "{ \"result\": \"api-key missing\"}",
"Headers": {}
}
}
- Home
- What is WireMock.Net
- WireMock.Org
- References
- Settings
- Admin REST API
- Proxying
- Stubbing
- Webhook
- Request Matching
- Response Templating
- Unit Testing
- Using WireMock
- Advanced
- Errors