Stubs
Writing stubs can be challenging and time-consuming. Stubr tries to assist by providing IDE completion or by recording live traffic into stubs. But you still have to know how to write a stub and what helpers you have in order to relax your stubs as much as possible.
You will find here in a single snippet ALL the fields/helpers available to you:
{
"id": "82d86e05-9ee0-44ca-9a8d-1fc6f719437e", // (optional) unique stub identifier. Returned in 'Matched-Stub-Id' header
"priority": 1, // (optional) helps solving interlaced conditions (many stubs match the request). 1 is the highest priority, 255 the lowest
"request": {
"method": "GET", // (optional) http method. Can be "ANY" to match any method. Defaults to "ANY"
"urlPath": "/api/exact-uri", // exact URI match
"urlPathPattern": "/api/regex-uri/([a-z]{4})", // URI must match regex
"urlPattern": "/api/regex-uri/([a-z]{4})\\?and=([a-z]{4})", // URI & query must match regex
"url": "/api/uri?age=young", // raw URI + query parameters by equality matching
"queryParameters": {
"firstname": { "equalTo": "beltram" }, // by equality matching (can also be an int, or a boolean)
"lastname": { "equalTo": "maldant", "caseInsensitive": true }, // case insensitve equality
"age": { "absent": true }, // must be absent
"city": { "contains": "a" }, // must contain the letter 'a'
"title": { "matches": "([A-Za-z]+)" }, // must match regex
"job": { "doesNotMatch": "([A-Za-z]+)" }, // or must not match regex
},
"headers": {
"content-type": { "equalTo": "application/json" } // by equality matching
// .. then all matchers described above for query parameters are also applicable here
},
"basicAuth" : { // exact Basic authentication matching
"username": "user",
"password": "pass"
},
"jwtAuth": {
"equalTo": "eyJhbGciOiJSUzI1NiJ9.e30.MBkQ...", // plain JWT token
"alg": {
"equalTo": "RS256", // JWT algorithm by equality matcher
"oneOf": ["RS256", "HS256"] // JWT must contain one of these algorithms
},
"payloadPatterns": [
// all matchers available in 'bodyPatterns' ⬇️
]
},
"bodyPatterns": [
{ "equalToJson": {"name": "bob"} }, // strict json request body equality
{ "equalToJson": {"name": "bob"}, "ignoreExtraElements": true }, // ignore extra json fields supplied in request body. Default to false.
{ "equalToJson": {"name": "bob"}, "ignoreArrayOrder": true }, // ignore array items order. Default to false.
{ "matchesJsonPath": "$.name" }, // must just match json path
{ "matchesJsonPath": "$.consoles[?(@.name == 'xbox')]" }, // must match json path + equality
{ "matchesJsonPath": "$.consoles[?(@.price > 200)]" }, // must match json path + bound
{ "expression": "$.name", "contains": "at" }, // must match json path + contain the string 'at'
{ "expression": "$.user", "equalToJson": { "name": "bob" } }, // must match json path + be equal
{ "binaryEqualTo": "AQID" /* Base 64 */ } // byte array equality
]
},
"response": {
"status": 200, // (required) response status
"fixedDelayMilliseconds": 2000, // delays response by 2 seconds
"delayDistribution": { // a random delay..
"type": "lognormal", // ..with logarithmic distribution
"median": 100, // The 50th percentile of latencies in milliseconds
"sigma": 0.1 // Standard deviation. The larger the value, the longer the tail
},
"jsonBody": { // json response body (automatically adds 'content-type:application/json' header)
"name": "john",
"surnames": [ "jdoe", "johnny" ]
},
"body": "Hello World !", // text response (automatically adds 'Content-Type:text/plain' header)
"base64Body": "AQID", // binary Base 64 body
"bodyFileName": "tests/stubs/response.json", // path to a .json or .txt file containing the response
"bodyFileName": "tests/stubs/{{request.pathSegments.[1]}}.json", // supports templating
"headers": {
"content-type": "application/pdf" // returns this response header
},
// ..now response templating
// it uses handlebars and allows you to define dynamic response based upon the content of the request
// it can be used in "jsonBody", "body", "bodyFileName" or "headers"
"transformers": ["response-template"], // required to activate response templating
"jsonBody": {
"url-path-and-query": "{{request.url}}",
"url-path": "{{request.path}}",
"url-path-segments": "{{request.pathSegments.[1]}}", // returns 'two' given '/one/two/three' path
"query": "{{request.query.kind}}", // returns 'comics' given '/api/books?kind=comics'
"multi-query": "{{request.query.kind.[1]}}", // returns 'novel' given '/api/books?kind=comics&kind=novel'
"method": "{{request.method}}", // http request method e.g. "POST"
"header": "{{request.headers.Content-Type}}", // returns request header with given key
"multi-header": "{{request.headers.cache-control.[0]}}", // returns first value of "cache-control" values
"body": "{{request.body}}", // returns raw request body
"from-request": "{{jsonPath request.body '$.name'}}", // takes field 'name' from json request body
"now": "{{now}}", // current datetime (UTC)
"now-fmt": "{{now format='yyyy/MM/dd'}}", // with custom Java SimpleDateFormat
"now-fmt-epoch": "{{now format='epoch'}}", // epoch in milliseconds
"now-fmt-unix": "{{now format='unix'}}", // epoch in seconds
"now-positive-offset": "{{now offset='3 days'}}", // human time positive offset
"now-negative-offset": "{{now offset='-3 days'}}", // human time negative offset
"now-with-timezone": "{{now timezone='Europe/Rome'}}",
"number-is-odd": "{{isOdd 3}}", // or 'isEven'
"string-capitalized": "{{capitalize mister}}", // or 'decapitalize'
"string-uppercase": "{{upper mister}}", // or 'lower'
"string-replace": "{{replace request.body 'a' 'b'}}", // e.g. given "Handlebars" in request body returns "Hbndlebbrs"
"number-stripes": "{{stripes request.body 'if-even' 'if-odd'}}",
"string-trim": "{{trim request.body}}", // removes leading & trailing whitespaces
"size": "{{size request.body}}", // string length or array length
"base64-encode": "{{base64 request.body padding=false}}", // padding is optional and defaults to true
"base64-decode": "{{base64 request.body decode=true}}",
"url-encode": "{{urlEncode request.header.x-raw}}",
"url-decode": "{{urlEncode request.header.x-encoded decode=true}}",
// you can also use 'any*' helpers. They will produce a random value
"regex": "{{anyRegex '[a-z]{4}'}}", // generate a random string matching regex
"string": "{{anyNonEmptyString}}", // or '{{anyNonEmptyString}}'
"alphanum": "{{anyAlphaNumeric}}",
"boolean": "{{anyBoolean}}",
"uuid": "{{anyUuid}}",
"ip": "{{anyIpAddress}}", // e.g. '127.0.0.1'
"host": "{{anyHostname}}", // e.g. 'https://github.com'
"email": "{{anyEmail}}", // e.g. 'john.doe@gmail.com'
"enum": "{{anyOf 'alpha' 'beta' 'gamma'}}", // returns randomly one of those 3 values
"number": "{{anyNumber}}", // integer or float
"integer": "{{anyI32}}", // also all Rust int types (u32, u8, i64 etc..)
"float": "{{anyFloat}}",
"anyDate": "{{anyDate}}" // or 'anyTime', 'anyDatetime', 'anyIso8601'
}
}
}