mountebank

mountebank - over the wire test doubles

Fork me on GitHub

the apothecary

Getting Started

Install:


npm install -g mountebank

The option above requires node.js of v4 or higher to already be installed, but mountebank does not believe in making you fiddle with a tech stack just to get up and running. Completely self-contained installation options are available on the install page.

Run:


mb

By default, mountebank listens on port 2525, but that's not the port that your imposters (test doubles) will listen on. To show a couple different kinds of imposters, let's create both an http imposter and a tcp one. We'll use the curl command line tool to call mountebank's api. The following command creates the http imposter, listening on port 4545, by POSTing to http://localhost:2525/imposters with the given body. The predicates are optional - if you don't include any, the stub always matches, and the response is always sent.

The contracts page provides an easy to use exploration of the JSON structure.


curl -i -X POST -H 'Content-Type: application/json' http://localhost:2525/imposters --data '{
  "port": 4545,
  "protocol": "http",
  "stubs": [{
    "responses": [
      { "is": { "statusCode": 400 }}
    ],
    "predicates": [{
      "and": [
        {
          "equals": {
            "path": "/test",
            "method": "POST",
            "headers": {
              "Content-Type": "application/json"
            }
          }
        },
        {
          "not": {
            "contains": {
              "body": "requiredField"
            },
            "caseSensitive": true
          }
        }
      ]
    }]
  }]
}'

Let's test it out:


curl -i -X POST -H 'Content-Type: application/json' http://localhost:4545/test --data '{"optionalField": true}'

HTTP/1.1 400 Bad Request
Connection: close
Date: Sat, 04 Jan 2014 02:48:16 GMT
Transfer-Encoding: chunked

Had we not tailored the request to match the predicates, we would have instead received the default response. For instance, let's send a request that leaves off the Content-Type:


curl -i -X POST http://localhost:4545/test --data '{"optionalField": true}'

HTTP/1.1 200 OK
Connection: close
Date: Sat, 04 Jan 2014 02:48:16 GMT
Transfer-Encoding: chunked

mountebank can stub binary tcp equally well, which is convenient when your application integrates with a downstream system using one of the myriad binary RPC protocols. Those protocols tend to rely on language-specific serialization to return an object graph. Your test can use the same serialization code to create a binary stream of the object you want the imposter to return during an RPC call, and encode it as a base64 string. That string is what you send to the imposter. In the example below, we're telling the imposter to respond with a base64-encoded string of "hello, world!" when a tcp request containing the string "sayHello" is sent to port 5555, which could correspond to the method name serialized in the RPC call:


curl -i -X POST -H 'Content-Type: application/json' http://localhost:2525/imposters --data '{
  "port": 5555,
  "protocol": "tcp",
  "mode": "binary",
  "stubs": [{
    "responses": [
      { "is": { "data": "aGVsbG8sIHdvcmxkIQ==" }}
    ],
    "predicates": [{ "contains": { "data": "c2F5SGVsbG8=" } }]
  }]
}'

We'll use nc (netcat) to make the tcp request, which is like telnet but easier to script.


echo "Calling sayHello over binary protocol" | nc localhost 5555

hello, world!

Finally, we can shut down both imposters by issuing an HTTP DELETE to both imposters, which are identified by the port number on the URL:


curl -X DELETE http://localhost:2525/imposters/4545
curl -X DELETE http://localhost:2525/imposters/5555

Explore more in the links on the left. Don't hesitate to ask for help!