mountebank

mountebank - over the wire test doubles

Fork me on GitHub

the apothecary

API Overview

mountebank uses a basic REST style API with standard HTTP status codes. Every effort has gone into providing response bodies to help you diagnose the problems. Each error response returned will have a code and message at a minimum. If extra information is available, mountebank will happily pass it to you. If you get stuck, email the group on the support page, along with your logs, and mountebank will happily assist you.

Capabilities

mountebank supports the following capabilities:

Capability Request Body Response Body
Get entry hypermedia home
Create a single imposter imposter imposter
Get a single imposter imposter
Add a stub to an existing imposter add stub imposter
Overwrite a stub of an existing imposter stub imposter
Overwrite all stubs of an existing imposter stubs imposter
Remove a stub of an existing imposter imposter
Delete a single imposter imposter
Delete saved proxy responses from an imposter
Overwrite all imposters with a new set of imposters imposters imposters
Get a list of all imposters imposters
Delete all imposters imposters
Get mountebank configuration and process information config
Get the logs logs

Get entry hypermedia

GET /

Response contract: home

This endpoint exists for those who aspire to the upper echelons of REST, using hypermedia as the engine of application state. For those with more humble aspirations, mountebank provides URL templates for all capabilities.

GET / HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 226
Date: Sun, 05 Jan 2014 16:16:08 GMT
Connection: keep-alive

{
  "_links": {
    "imposters": { "href": "http://localhost:36181/imposters" },
    "config": { "href": "http://localhost:36181/config" },
    "logs": { "href": "http://localhost:36181/logs" }
  }
}

Create a single imposter

POST /imposters

Request contract: imposter

Response contract: imposter

Though he's not proud to admit it, mountebank employs an army of imposters to fulfill your orders. Because your needs are varied and sundry, his imposters are all different, and all are identified by a port number and associated with a protocol. The value you get out of mountebank always starts by creating an imposter, which represents a test double listening on a socket.

Parameters:

If you don't need stubbing, then the port and protocol are all you need. The parameters each type of imposter accepts are explained on the page for the particular protocol you're interested in. See the protocols section on the sidebar on the left.

mountebank expects that you will be responsible for providing the port, since you'll need to configure the application under test with the same port. However, the port is not required, and if you do not include it in the request, mountebank will randomly assign one for you and return the port number in the response.

POST /imposters HTTP/1.1
Host: localhost:36181
Accept: application/json
Content-Type: application/json

{
  "port": 4545,
  "protocol": "http"
}
HTTP/1.1 201 Created
Access-Control-Allow-Origin: *
Location: http://localhost:36181/imposters/4545
Content-Type: application/json; charset=utf-8
Content-Length: 298
Date: Sun, 05 Jan 2014 16:28:40 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

You can also initialize stubs in the POST call.

mountebank expects you to configure your application under test to point to the imposter. In the case above, that would mean that your application has an http dependency configured to http://localhost:4545. To retrieve a list of all imposters, simply issue a GET:

Get a single imposter

GET /imposters/:port

Response contract: imposter

Retrieving an imposter is generally useful for one the following reasons:

Query Parameters:

Name Type Description
replayable boolean Set to true to retrieve the minimum amount of information for creating the imposter in the future. This leaves out the requests array, the matches array, and any hypermedia.
removeProxies boolean Set to true to remove all proxy responses (and stubs) from the response. This is useful in record-playback scenarios where you want to seed the imposters with proxy information but leave it out on subsequent test runs. You can recreate the imposter in the future by using the response.
GET /imposters/4545 HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 298
Date: Sun, 05 Jan 2014 16:59:33 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Had we set the replayable query parameter, the requests array and _links elements would not be there. If we had any stubs, the matches array would also not be present regardless of whether we ran mb with the --debug command line parameter or not. None of those fields are used during the creation of an imposter.

GET /imposters/4545?replayable=true HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 82
Date: Sun, 05 Jan 2014 16:59:33 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "recordRequests": false,
  "stubs": []
}

Add a stub to an existing imposter

Request contract: add stub

Response contract: imposter

POST /imposters/:port/stubs

In most cases, you would add the stubs at the time you create the imposter, but this call allows you to add a stub to an existing imposter without restarting it. You can add the new stub at any index between 0 and the end of the existing array. If you leave off the index field, the stub will be added to the end of the existing stubs array. On a successful request, mountebank will return the updated imposter resource.

POST /imposters/4545/stubs HTTP/1.1
Host: localhost:36181
Accept: application/json

{
  "index": 0,
  "stub": {
    "responses": [{
      "is": {
        "body": "Hello, world!"
      }
    }]
  }
}
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 548
Date: Wed, 19 Jun 2019 01:00:55 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [{
    "responses": [{
      "is": {
        "body": "Hello, world!"
      }
    }],
    "_links": {
      "self": { "href": "http://localhost:36181/imposters/4545/stubs/0" }
    }
  }],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Change a stub in an existing imposter

PUT /imposters/:port/stubs/:stubIndex

Request contract: stub

Response contract: imposter

Use this endpoint to overwrite an existing stub without restarting the imposter. The stubIndex must match the array index of the stub you wish to change. Pass the new stub as the body of the request. The response will provide the updated imposter resource.

PUT /imposters/4545/stubs/0 HTTP/1.1
Host: localhost:36181
Accept: application/json

{
  "responses": [{
    "is": {
      "body": "Goodbye, world!"
    }
  }]
}
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 550
Date: Wed, 19 Jun 2019 01:00:55 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [{
    "responses": [{
      "is": {
        "body": "Goodbye, world!"
      }
    }],
    "_links": {
      "self": { "href": "http://localhost:36181/imposters/4545/stubs/0" }
    }
  }],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Overwrite all stubs in an existing imposter

PUT /imposters/:port/stubs

Request contract: stubs

Response contract: imposter

Use this endpoint to overwrite all existing stub without restarting the imposter. The response will provide the updated imposter resource.

PUT /imposters/4545/stubs HTTP/1.1
Host: localhost:36181
Accept: application/json

{
  "stubs": [{
    "responses": [{
      "is": { "body": "New stub" }
    }]
  }]
}
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 543
Date: Wed, 19 Jun 2019 01:00:55 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [
    {
      "responses": [{
        "is": { "body": "New stub" }
      }],
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4545/stubs/0" }
      }
    }
  ],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Remove a single stub from an existing imposter

DELETE /imposters/:port/stubs/:stubIndex

Response contract: imposter

Use this endpoint to remove the stub at the given array index without restarting the imposter. The response will provide the updated imposter resource.

DELETE /imposters/4545/stubs/0 HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 298
Date: Wed, 19 Jun 2019 01:00:55 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Delete a single imposter

DELETE /imposters/:port

Response contract: imposter

As mentioned above, typically you want to delete the imposter after each test run. This frees up the socket and removes the resource. As a convenience, the DELETE call also returns the imposter representation just like a GET imposter would. This allows you to optimize the number of REST calls made during a test run when looking at the requests array for mock verification.

Query Parameters:

Name Type Description
replayable boolean Set to true to retrieve the minimum amount of information for creating the imposter in the future. This leaves out the requests array, the matches array, and any hypermedia.
removeProxies boolean Set to true to remove all proxy responses (and stubs) from the response. This is useful in record-playback scenarios where you want to seed the imposters with proxy information but leave it out on subsequent test runs. You can recreate the imposter in the future by using the response.
DELETE /imposters/4545 HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 298
Date: Sun, 05 Jan 2014 16:59:33 GMT
Connection: keep-alive

{
  "protocol": "http",
  "port": 4545,
  "numberOfRequests": 0,
  "recordRequests": false,
  "requests": [],
  "stubs": [],
  "_links": {
    "self": { "href": "http://localhost:36181/imposters/4545" },
    "stubs": { "href": "http://localhost:36181/imposters/4545/stubs" }
  }
}

Delete saved proxy responses from an imposter

DELETE /imposters/:port/savedProxyResponses

Proxy stubs save all responses returned from downstream systems. Usually this is what you want, as they can be played back at a later time without the actual downstream system available. However, if you need to clear them but keep the stubs intact, you can do so with this call.

Note that you can prevent the proxy from saving responses by setting the mode to proxyTransparent.

Overwrite all imposters with a new set of imposters

PUT /imposters

Request contract: imposters

Response contract: imposters

Sometimes you want to create a batch of imposters in a single call, overwriting any imposters already created. This call is destructive - it will first delete all existing imposters. The output of a GET /imposters?replayable=true can directly be replayed through this call. This call is also used during startup if you set the --configfile command line flag.

Parameters:

You must provide mountebank an imposters array. Each element in the array is the same as what's needed to create a single imposter, the parameters for which vary by protocol. View the protocol pages on the left for details.

PUT /imposters HTTP/1.1
Host: localhost:36181
Content-Type: application/json

{
  "imposters": [
    {
      "protocol": "http",
      "port": 4546
    },
    {
      "protocol": "tcp",
      "port": 4547,
      "mode": "binary"
    },
    {
      "protocol": "smtp",
      "port": 4548
    }
  ]
}

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 898
Date: Sun, 05 Jan 2014 16:59:33 GMT
Connection: keep-alive

{
  "imposters": [
    {
      "protocol": "http",
      "port": 4546,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4546" },
        "stubs": { "href": "http://localhost:36181/imposters/4546/stubs" }
      }
    },
    {
      "protocol": "tcp",
      "port": 4547,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4547" },
        "stubs": { "href": "http://localhost:36181/imposters/4547/stubs" }
      }
    },
    {
      "protocol": "smtp",
      "port": 4548,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4548" },
        "stubs": { "href": "http://localhost:36181/imposters/4548/stubs" }
      }
    }
  ]
}

Get a list of all imposters

GET /imposters

Response contract: imposters

This is where you will come to retrieve a list of all active imposters. By default, mountebank returns some basic information and hypermedia. If you want more information, either get the single imposter or use the replayable flag.

Query Parameters:

Name Type Description
replayable boolean Set to true to retrieve the minimum amount of information for replaying the set of imposters in the future through a mass create call. This leaves out the requests array, the matches array, and any hypermedia.
removeProxies boolean Set to true to remove all proxy responses (and stubs) from the response. This is useful in record-playback scenarios where you want to seed the imposters with proxy information but leave it out on subsequent test runs. You can recreate the imposter in the future by using the response.
GET /imposters HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 898
Date: Sun, 05 Jan 2014 16:58:25 GMT
Connection: keep-alive

{
  "imposters": [
    {
      "protocol": "http",
      "port": 4546,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4546" },
        "stubs": { "href": "http://localhost:36181/imposters/4546/stubs" }
      }
    },
    {
      "protocol": "tcp",
      "port": 4547,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4547" },
        "stubs": { "href": "http://localhost:36181/imposters/4547/stubs" }
      }
    },
    {
      "protocol": "smtp",
      "port": 4548,
      "numberOfRequests": 0,
      "_links": {
        "self": { "href": "http://localhost:36181/imposters/4548" },
        "stubs": { "href": "http://localhost:36181/imposters/4548/stubs" }
      }
    }
  ]
}

Delete all imposters

DELETE /imposters

Response contract: imposters

The surest way to reset to a clean slate is to delete all imposters. Any imposter sockets mountebank has open will be closed, and the response body will contain exactly what you need to mass create the same imposters in the future.

Query Parameters:

Name Type Description
replayable boolean Defaults to true. Set to false to retrieve the matches and requests arrays with the response. You can still mass create using this JSON; it just has extraneous information.
removeProxies boolean Set to true to remove all proxy responses (and stubs) from the response. This is useful in record-playback scenarios where you want to seed the imposters with proxy information but leave it out on subsequent test runs. You can recreate the imposters in the future by using the response.
DELETE /imposters HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 370
Date: Sun, 05 Jan 2014 16:58:25 GMT
Connection: keep-alive

{
  "imposters": [
    {
      "protocol": "http",
      "port": 4546,
      "recordRequests": false,
      "stubs": []
    },
    {
      "protocol": "tcp",
      "port": 4547,
      "recordRequests": false,
      "mode": "binary",
      "stubs": []
    },
    {
      "protocol": "smtp",
      "port": 4548,
      "recordRequests": false,
      "stubs": []
    }
  ]
}

Get mountebank configuration and process information

GET /config

Response contract: config

If you want to know about the environment mountebank is running it, this resource will give you what you need. It describes the version, command line flags, and process information.

GET /config HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 550
Date: Sat, 13 May 2017 23:41:31 GMT
Connection: keep-alive

{
  "version": "2.1.1",
  "options": {
    "port": 36181,
    "pidfile": "mb-grunt.pid",
    "logfile": "mb-grunt.log",
    "allowInjection": true,
    "mock": true,
    "debug": true,
    "localOnly": true,
    "noParse": false,
    "nologfile": false,
    "loglevel": "info",
    "ipWhitelist": [
      "*"
    ],
    "protofile": "protocols.json"
  },
  "process": {
    "nodeVersion": "v5.8.0",
    "architecture": "x64",
    "platform": "darwin",
    "rss": 43393024,
    "heapTotal": 32266016,
    "heapUsed": 20060904,
    "uptime": 69.108,
    "cwd": "/Users/bbyars/src/mountebank"
  }
}

Get the logs

GET /logs

Response contract: logs

Query Parameters:

Name Type Description
startIndex integer Set to array index of the first log entry you want returned.
endIndex integer Set to the array index of the last log entry you want returned
GET /logs?startIndex=0&endIndex=1 HTTP/1.1
Host: localhost:36181
Accept: application/json
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Vary: Accept
Content-Type: application/json; charset=utf-8
Content-Length: 5249
Date: Sat, 13 May 2017 23:45:07 GMT
Connection: keep-alive

{
  "logs": [
    {
      "message": "[mb:36181] mountebank v2.1.1 now taking orders - point your browser to http://localhost:36181/ for help",
      "level": "info",
      "timestamp": "2015-10-20T03:33:23.018Z"
    },
    {
      "message": "[mb:36181] Running with --allowInjection set. See http://localhost:36181/docs/security for security info",
      "level": "warn",
      "timestamp": "2015-10-20T03:33:23.019Z"
    }
  ]
}

In the rare scenario where mountebank is hosted on a different server and you need access to the logs, they are accessible through this endpoint.