v12.6.1

Functional Mocks

Node 22.18+ and 23.6+ support TypeScript by default.

You can write mocks in JavaScript or TypeScript

api/foo.GET.200.js

export default (req, response) => {
  // These two lines are not needed but you can change their values
  /* response.statusCode = 200 */  // default derived from filename
  /* response.setHeader('Content-Type', 'application/json') */ // unconditional default
  return JSON.stringify({ foo: 'bar' })
}

Return a string | Buffer | Uint8Array, but don’t call response.end(). async functions are supported.

Custom HTTP Handlers

For example, you can intercept requests to write to a database. Or act based on some query string value, etc. In summary, you get Node’s request, response as arguments, so you can think of Mockaton as a router, but in the handlers you return, instead of ending the response.

Example A: JSON body parser and in-memory database

Imagine you have an initial list of colors, and you want to concatenate newly added colors.

api/colors.POST.201.js
import { parseJSON } from 'mockaton'

export default async function insertColor(req, response) {
  const color = await parseJSON(req)
  globalThis.newColorsDatabase ??= []
  globalThis.newColorsDatabase.push(color)
  return JSON.stringify({ msg: 'CREATED' })
}

api/colors.GET.200.js
import colorsFixture from './colors.json' with { type: 'json' }

export default function listColors() {
  return JSON.stringify([
    ...colorsFixture,
    ...(globalThis.newColorsDatabase || [])
  ])
}

Example B: Parse query string params

api/list?limit=[my-limit].GET.200.js
import { parseQueryParams } from 'mockaton'

export default function (req) {
  const searchParams = parseQueryParams(req.url)
  const limit = Number(searchParams.get('limit'))
  return JSON.stringify({ limit })
}

Example C: Parse splats

api/company/[companyId]/user/[userId].GET.200.js
import { parseSplats } from 'mockaton'

export default function (req, response) {
  const { companyId, userId } = parseSplats(req.url, import.meta.filename)
  return JSON.stringify({ companyId, userId })
}

What if I need to serve a static .js or .ts?

Option A: Put it in your config.staticDir without the .GET.200.js extension. Mocks in staticDir take precedence over mocksDir/*.

Option B: Read it and return it. For example:

import { readFileSync } from 'node:fs'

export default function (_, response) {
  response.setHeader('Content-Type', 'application/javascript')
  return readFileSync('./some-dir/foo.js', 'utf8')
}