Skip to main content

<mockData>

Description

The <mockData> tag sets up fake responses to HTTP requests made from the bot script (mock objects).

When automated tests are run and $http.query is called from the script (or a shorthand method like $http.get), the test runner checks whether there is a corresponding <mockData> tag in the test with the same parameters and request body as the ones passed to the HTTP request.

  • If such a tag exists and its URL and body match the expected ones, the test runner uses the response specified in <mockData> as the HTTP response body returned by the method call.

  • If the script contains an $http method call but there is no corresponding <mockData>, the HTTP request is assumed to have failed and returns no data. This will most likely result in the test case also being failed.

No actual HTTP requests are made during test runs.

tip
This behavior can be overridden. Set the integration="true" attribute for the <test> or <test-case> elements to allow the test runner to make real HTTP requests throughout the whole test or a single test case. In this case, specifying <mockData> is not necessary.
caution
Bear in mind that if you use integration="true" and run automated tests fairly frequently, real HTTP requests can quickly drain your API usage quotas or have some other unintended consequences.
It is recommended to use this attribute sparingly and reserve it for integration tests — tests specifically designed to verify the integration between the bot script and the HTTP API it relies on.

Structure

<mockData> supports the following child elements.

Request URL and parameters

  • <query> specifies the request URL. This element is required.

    • It has a method attribute — the HTTP verb used for executing the request. The default value is GET.
    • The body of the <query> element contains the URL where the HTTP request is sent. It cannot be empty.
  • <parameters> contains values for interpolated URL parameters. This element is optional.

To specify variable values such as query parameters, you can either put them directly within <query> or use a separate <parameters> element.

The <parameters> child elements should be written as <parameter-name>parameter-value</parameter-name>, and all parameter values in <query> should be substituted with placeholders like ${parameter-name}.

caution
Don’t forget to escape special characters when writing XML tests: substitute & with &amp;, < with &lt;, > with &gt;.
<mockData>
<query>https://httpbin.org/get?foo=bar&amp;text=&quot;Hello, world!&quot;</query>
<!-- ... -->
</mockData>

Request body

The optional <body> element contains the request body.

If the mock object has a <body> child element, an additional check is performed when executing an HTTP request to verify that the expected request body matches the one actually passed from the script. The body of this element should be a JSON object or primitive expected to be passed in the request body.

The following optional attributes can be provided for the tag:

  • strictMatch determines how strictly the mock object is matched against the actual request body. The default value is false.

    • When strict match is disabled (set to false), only the property values specified in <body> are checked to be the same as the corresponding values in the request body.
    • If strict match is set to true, the full <body> contents and the request body are checked to be exactly the same.
  • field is a JsonPath expression for a specific request body property. If provided, only this property is matched rather than the whole request body.

<mockData>
<query method="POST">https://httpbin.org/post</query>
<body>
{
"foo": "bar"
}
</body>
<!-- ... -->
</mockData>

Response

<response> contains the response returned by the mock object as the response from the server. This element is required. The element body contains the raw response.

caution
The $http.query return value contains the HTTP response in the data property as well as a number of extra fields like isOk, status, and others. Do not add these extra properties in <response>. Only the HTTP response from data is needed.

The tag supports the following attributes:

  • status is the HTTP status code, 200 by default.
  • type is the response type, json by default.
    • If the response type is json or xml, the response is parsed and returned to the script as a JS object.
    • Otherwise the response is returned as a string.
caution
A mismatch between the <response> body format and the type provided will cause a syntax error when the bot is deployed.
<mockData>
<query>https://httpbin.org/json</query>
<response>
{
"slideshow": {
"title": "Sample Slide Show"
}
}
</response>
</mockData>

Response as a string

When the response type is neither json nor xml, the response is returned to the script as a string including all whitespace characters. The responses from the following examples will be different:

<mockData>
<query>https://httpbin.org/get</query>
<response type="text">ok</response>
</mockData>
$http.query("http://httpbin.org/get"); // => {..., data: "ok"}

Empty response

<response> can be an empty element. In that case, the mock HTTP response returned to the script is an empty object.

tip
An example use case for empty responses is mimicking 204 No Content, when the server returns only headers with no body.
<mockData>
<query>https://httpbin.org/status/204</query>
<response status="204"/>
</mockData>

Frequently asked questions

Where should I put mock objects?

<mockData> elements can be placed in either <test> or <test-case> elements.

  • Mock objects within <test> are available to all test cases belonging to this test. This is useful when the test cases verify some common piece of functionality.
  • Mock objects within <test-case> are only used for running this particular test case. They are unavailable to other test cases.

What order should mock objects be in?

  • Mock objects within <test> can be placed anywhere after, before, or between test cases.
  • Mock objects within <test-case> should precede the <q> elements which emulate queries triggering HTTP requests.

How many mock objects should there be?

Every test case should have as many mock objects as there are HTTP requests made when the test case is run.

tip
However, if several identical HTTP requests are made throughout one test case and they are expected to return the same responses, only one mock object is needed to check them.

Can I check different responses to the same HTTP request?

You can check the same HTTP request returning different responses throughout one test case. Every <q> tag triggering a request should have a corresponding mock object.

If several matching <mockData> elements precede <q>, only the response from the last one will be used. Other mock objects will be ignored.

The example below illustrates this:

state: ExternalCall
q!: test
script:
$temp.res = $http.get("https://httpbin.org/get");
a: {{$temp.res.data}}
<test-case>
<!-- This mock object is ignored -->
<mockData>
<query>https://httpbin.org/get</query>
<response type="text">1</response>
</mockData>
<!-- This mock object is used for both requests made below -->
<mockData>
<query>https://httpbin.org/get</query>
<response type="text">2</response>
</mockData>

<q>test</q>
<a>2</a>
<q>test</q>
<a>2</a>

<!-- This mock object is only used for the request made below -->
<mockData>
<query>https://httpbin.org/get</query>
<response type="text">3</response>
</mockData>

<q>test</q>
<a>3</a>
</test-case>

How to use

Mocking query parameters

The example below is adapted from the tutorial on creating a bot with API requests. It contains a mock object for testing the state where the bot reports the current weather.

<test>
<mockData>
<query>http://api.openweathermap.org/data/2.5/weather?appid=${appid}&amp;units=${units}&amp;lang=${lang}&amp;q=${q}</query>
<parameters>
<appid>***</appid> <!-- Replace the placeholder with your API key -->
<units>metric</units>
<lang>en</lang>
<q>London</q>
</parameters>
<response>
{
"weather": [
{
"main": "Clear",
"description": "clear sky"
}
],
"main": {
"temp": 9.82
}
}
</response>
</mockData>

<test-case>
<q>/start</q>
<a>Hello! I’m your virtual assistant. I can tell you the current weather in any city. Just tell me the city.</a>
<q>London</q>
<a>Today in London: clear sky, 10 °C.</a>
</test-case>
</test>

Mocking the request body

The following example illustrates different ways how the request body can be matched against the contents of <body>.

state: ExternalCall
q!: test
script:
$temp.res = $http.post("https://httpbin.org/post", {
body: {
bodyParam1: "text1",
bodyParam2: "text2",
bodyObject: {
bodyParam3: 100,
bodyParam4: false
}
}
});
a: {{$temp.res.data}}
<test>
<!-- The actual request body exactly matches the expected one. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<body strictMatch="true">
{
"bodyParam1": "text1",
"bodyParam2": "text2",
"bodyObject": {
"bodyParam3": 100,
"bodyParam4": false
}
}
</body>
<response type="text">ok 1</response>
</mockData>
<q>test</q>
<a>ok 1</a>
</test-case>

<!-- The values specified in <body> match the ones passed in the request. -->
<!-- A full match is not required because the `strictMatch` attribute is not set. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<body>
{
"bodyParam1": "text1",
"bodyParam2": "text2"
}
</body>
<response type="text">ok 2</response>
</mockData>
<q>test</q>
<a>ok 2</a>
</test-case>

<!-- The object in `<body>` is matched against the `bodyObject` property in the request body. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<body field="bodyObject">
{
"bodyParam3": 100,
"bodyParam4": false
}
</body>
<response type="text">ok 3</response>
</mockData>
<q>test</q>
<a>ok 3</a>
</test-case>

<!-- Here, the last mock object requires a full match against the `bodyObject` property. -->
<!-- Since the actual request body does not meet this condition, this mock object is ignored. -->
<!-- The preceding mock object is used instead. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<body field="bodyObject">
{
"bodyParam3": 100
}
</body>
<response type="text">ok 4</response>
</mockData>

<mockData>
<query method="POST">https://httpbin.org/post</query>
<body field="bodyObject" strictMatch="true">
{
"bodyParam3": 100
}
</body>
<response type="text">would not match</response>
</mockData>
<q>test</q>
<a>ok 4</a>
</test-case>

<!-- If no `<body>` is provided, only the URL and request method are used for matching. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<response type="text">ok 5</response>
</mockData>
<q>test</q>
<a>ok 5</a>
</test-case>

<!-- The mock object body can be a JSON primitive as well as an object. -->
<test-case>
<mockData>
<query method="POST">https://httpbin.org/post</query>
<body field="bodyParam2">"text2"</body>
<response type="text">ok 6</response>
</mockData>
<q>test</q>
<a>ok 6</a>
</test-case>
</test>