Mountebank: Over-the-Wire Test Doubles

2.9.1 · active · verified Wed Apr 22

Mountebank is an open-source, cross-platform, multi-protocol test double tool designed to mock services over the wire. It enables developers to create configurable mock API endpoints for various protocols like HTTP, HTTPS, TCP, and SMTP. Mountebank primarily operates by creating "imposters" that listen on specified ports, responding to requests based on defined "stubs" which include predicates (conditions) and responses. This approach allows for isolated and repeatable testing of applications, reducing dependencies on external services and improving development efficiency. The project recently transitioned to a community-driven effort under the `mountebank-testing` GitHub organization, with the npm package name changing from `mountebank` to `@mbtest/mountebank`. It maintains a consistent release cadence, with several updates in the past year (v2.9.1 to v2.9.4). Key differentiators include its multi-protocol support, a powerful REST API for dynamic configuration, and the ability to extend functionality through JavaScript injection.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to install Mountebank globally, start the `mb` server, programmatically create a simple HTTP GET imposter via its REST API, and then verify the mock response.

import { strict as assert } from 'assert';
import { exec } from 'child_process';
import util from 'util';

const execPromise = util.promisify(exec);

const imposterConfig = {
  port: 4545,
  protocol: 'http',
  stubs: [
    {
      predicates: [{
        equals: { path: '/test', method: 'GET' }
      }],
      responses: [
        { is: { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Hello from Mountebank!' }) } }
      ]
    }
  ]
};

async function runMountebankQuickstart() {
  let mbProcess;
  try {
    console.log('1. Installing @mbtest/mountebank globally...');
    await execPromise('npm install -g @mbtest/mountebank');
    console.log('   Installed successfully.');

    console.log('2. Starting Mountebank server...');
    // Using `exec` to start mb in the background, ensure --allowInjection for future use cases
    // and --loglevel debug for better visibility.
    mbProcess = exec('mb --allowInjection --loglevel debug');
    mbProcess.stdout.pipe(process.stdout);
    mbProcess.stderr.pipe(process.stderr);

    // Give Mountebank a moment to start up
    await new Promise(resolve => setTimeout(resolve, 3000)); 
    console.log('   Mountebank server started (admin UI at http://localhost:2525).');

    console.log('3. Creating an HTTP imposter...');
    await fetch('http://localhost:2525/imposters', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(imposterConfig)
    });
    console.log('   Imposter created on port 4545.');

    console.log('4. Testing the mocked service...');
    const response = await fetch('http://localhost:4545/test');
    const data = await response.json();

    assert.equal(response.status, 200, 'Expected status code 200');
    assert.deepEqual(data, { message: 'Hello from Mountebank!' }, 'Expected specific mock response');
    console.log('   Mocked service responded correctly:', data);

  } catch (error) {
    console.error('An error occurred:', error.message);
    process.exit(1);
  } finally {
    if (mbProcess) {
      console.log('5. Stopping Mountebank server...');
      // Terminate the mountebank process gracefully
      await execPromise('mb stop');
      console.log('   Mountebank server stopped.');
    }
  }
}

runMountebankQuickstart();

view raw JSON →