% title = 'predicates' description = 'The predicates supported by mountebank' %> <%- include('../../_header') -%>
In the absence of a predicate, a stub always matches, and there's never a reason to add more than one stub to an imposter. Predicates allow imposters to have much richer behavior by defining whether or not a stub matches a request. When multiple stubs are created on an imposter, the first stub that matches is selected.
Each predicate object contains one or more of the request fields as keys. Predicates are added to a stub in an array, and all predicates are AND'd together. The following predicate operators are allowed:
Operator | Description |
---|---|
equals |
The request field matches the predicate |
deepEquals |
Performs nested set equality on the request field, useful when
the request field is an object (e.g. the query field in http) |
contains |
The request field contains the predicate |
startsWith |
The request field starts with the predicate |
endsWith |
The request field ends with the predicate |
matches |
The request field matches the JavaScript regular expression defined with the predicate. |
exists |
If true , the request field must exist. If false ,
the request field must not exist. |
not |
Inverts a predicate |
or |
Logically or's two predicates together |
and |
Logically and's two predicates together |
inject |
Injects JavaScript to decide whether the request matches or not. See the injection page for more details. |
Predicates can be parameterized. mountebank accepts the following predicate parameters:
Parameter | Default | Description |
---|---|---|
caseSensitive |
false |
Determines if the match is case sensitive or not. This includes keys for objects such as query parameters. |
except |
"" |
Defines a regular expression that is stripped out of the request field before matching. |
xpath |
null |
Defines an object containing a selector string and, optionally, an
ns object field that defines a namespace map. The predicate's
scope is limited to the selected value in the request field. |
jsonpath |
null |
Defines an object containing a selector string. The predicate's
scope is limited to the selected value in the request field. |
See the equals
example below to see the caseSensitive
and
except
parameters in action. See the xpath page
for xpath
examples. See the jsonpath page
for jsonpath
examples.
Almost all predicates are scoped to a request field; see the protocol pages linked to from
the sidebar to see the request fields. inject
is the sole exception. It takes
a string function that accepts the entire request. See the
injection page for details.
The predicates work intuitively for base64-encoded binary data as well by internally
converting the base64-encoded string to a JSON string representing the byte array. For example,
sending "AQIDBA==" will get translated to "[1,2,3,4]", and predicates expecting "AgM=" will
get translated to "[2,3]". Even though "AQIDBA==" does not contain "AgM=", a contains
predicate will match, because "[1,2,3,4]" does contain "[2,3]". This works well for everything
but matches
, because any regular expression operators get encoded as binary.
mountebank recommends that you stay away from matches
if you're dealing in binary.
In mountebank's experience, contains
is the most useful predicate for binary
imposters, as even binary RPC data generally contains strings representing method names.
On occasion you may encounter multi-valued keys. This can be the case with querystrings
and HTTP headers that have repeating keys, for example ?key=first&key=second
.
In those cases, deepEquals
will require all the values (in any order) to match.
All other predicates will match if any value matches, so an equals
predicate
will match with the value of second
in the example above.
JSON predicates are also allowed, for example, to match HTTP
bodies. When the body contains an array, the logic above still applies: deepEquals
requires all values to match, and other predicates will match if any value in the array
matches.
You also have the option of specifying an array in the predicate definition. If you do so,
then all fields in the predicate array must match (in any order). Most predicates
will match even if there are additional fields in the actual request array; deepEquals
requires the array lengths to be equal. The following example shows this with a querystring:
POST /imposters HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
Content-Type: application/json
{
"port": 3333,
"protocol": "http",
"stubs": [
{
"predicates": [{
"deepEquals": {
"query": { "key": ["first", "second"] }
}
}],
"responses": [{
"is": {
"body": "Entire array matched"
}
}]
},
{
"predicates": [{
"equals": {
"query": { "key": ["first", "second"] }
}
}],
"responses": [{
"is": {
"body": "Subset of array matched"
}
}]
},
{
"predicates": [{
"equals": {
"query": { "key": "first" }
}
}],
"responses": [{
"is": {
"body": "A field in the array matched"
}
}]
}
]
}
First let's call the imposter matching both keys in the deepEquals
predicate. For it
to match, no other keys must be present, although the order does not matter.
GET /path?key=second&key=first HTTP/1.1
Host: localhost:3333
Since both keys match and there are no extraneous keys, we get our expected response from the first stub.
HTTP/1.1 200 OK
Connection: close
Date: Sat, 06 May 2017 02:30:31 GMT
Transfer-Encoding: chunked
Entire array matched
If we add a third key not specified by the predicate, it no longer matches the deepEquals
predicate. It does, however, match the equals
predicate, which supports matching a subset of arrays.
GET /path?key=second&key=first&key=third HTTP/1.1
Host: localhost:3333
Since both keys match, we get our expected response from the first stub.
HTTP/1.1 200 OK
Connection: close
Date: Sat, 06 May 2017 02:30:31 GMT
Transfer-Encoding: chunked
Subset of array matched
If the request is missing either array value specified in the predicate, it no longer matches.
GET /path?key=first&key=third HTTP/1.1
Host: localhost:3333
In this case, our third stub matches, because it does not use an array predicate, and one of the actual array values in the request matches the predicate definition
HTTP/1.1 200 OK
Connection: close
Date: Sat, 06 May 2017 02:30:31 GMT
Transfer-Encoding: chunked
A field in the array matched
DELETE /imposters/3333 HTTP/1.1
Host: localhost:<%= port %>
Accept: application/json
mountebank has special support for matching XML and JSON request fields, such as in an http body
or tcp data
field. Where XML or JSON predicates are used against string
fields,
mountebank will attempt to parse the field as XML or JSON and apply the given predicate. If he is unable to
parse the field, the predicate will fail; otherwise it will pass or fail according to the selected value.
See the xpath page for xpath
examples.
See the json page for json
examples.
The examples below use both HTTP and TCP imposters. The TCP examples use netcat (nc
)
to send TCP data over a socket, which is like telnet
, but makes the output easier to script.
The examples for binary imposters use the base64
command line tool to decode base64
to binary before sending to the socket.