The default formatter for mountebank allows you to use EJS (version 2.x) templates to split the test data into multiple files. This is particularly useful for separating out JavaScript injection functions and XML or JSON HTTP response bodies because you store them as multi-line files and rely on templating to turn them into JSON-friendly single line strings. It remains the default for backwards compatibility, even though EJS 3.x has made breaking changes.

mountebank will pass a stringify function into your templates that allows you to put multi-line strings in separate files. The example below is loosely based on the response injection example described on the Injection page, and shows the use of the stringify function. The path passed in to stringify is relative to the root file referenced in the configfile command line parameter. You can also pass a custom object, referenced as data in child templates, as the second parameter of stringify. This is useful if you want to reuse the same template but add some dynamic data. For an example, look at the stringify call in templates/originServer.ejs below, and using the custom field in templates/originXMLResponse.ejs.

Assuming the files below are in a relative directory called templates, you can initialize mb with the following command:

mb --configfile templates/imposters.ejs --allowInjection --localOnly

templates/imposters.ejs

{
  "imposters": [
    <% include originServer.ejs %>,
    <% include proxyServer.ejs %>
  ]
}

templates/originServer.ejs

{
  "port": 5555,
  "protocol": "http",
  "name": "origin",
  "stubs": [
    {
      "predicates": [{ "contains": { "headers": { "Content-Type": "xml" } } }],
      "responses": [{ "is": { "body": "<%- stringify('originXMLResponse.ejs', { value: 'first }) %>" }}]
    },
    {
      "responses": [{ "inject": "<%- stringify('originServerResponse.ejs') %>" }]
    }
  ]
}

templates/originXMLResponse.ejs

<rootNode>
  <childNode><%= '<' + '%= data.value %' + '>' %></childNode>
</rootNode>

templates/originServerResponse.ejs

(request, state, logger) => {
    logger.info('origin called');
    state.requests = state.requests || 0;
    state.requests += 1;
    return {
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ count: state.requests })
    };
}

templates/proxyServer.ejs

{
  "port": 4546,
  "protocol": "http",
  "name": "proxy",
  "stubs": [
    {
      "responses": [{ "inject": "<%- stringify('counter.ejs') %>" }],
      "predicates": [{
        "equals": {
          "method": "GET",
          "path": "/counter"
        }
      }]
    },
    {
      "responses": [{ "inject": "<%- stringify('proxy.ejs') %>" }]
    }
  ]
}

templates/counter.ejs

function (request, state) {
    var count = state.requests ? Object.keys(state.requests).length : 0;

    return {
        body: `There have been ${count} proxied calls`
    };
}

templates/proxy.ejs

function (request, state, logger, callback) {
    var cacheKey = request.method + ' ' + request.path;

    if (typeof state.requests === 'undefined') {
        state.requests = {};
    }

    if (state.requests[cacheKey]) {
        logger.info('Using previous response');
        callback(state.requests[cacheKey]);
    }

    var http = require('http'),
        options = {
            method: request.method,
            hostname: 'localhost',
            port: 5555,
            path: request.path,
            headers: request.headers
        },
        httpRequest = http.request(options, response => {
            var body = '';
            response.setEncoding('utf8');
            response.on('data', chunk => {
                body += chunk;
            });
            response.on('end', () => {
                var stubResponse = {
                        statusCode: response.statusCode,
                        headers: response.headers,
                        body
                    };
                logger.info('Successfully proxied: ' + JSON.stringify(stubResponse));
                state.requests[cacheKey] = stubResponse;
                callback(stubResponse);
            });
        });
    httpRequest.end();
}