DEV Community

Amazia Gur
Amazia Gur

Posted on

Stop running a JVM just to mock an API in your CI pipeline

If you've set up WireMock in a CI pipeline before, you know the pattern: pull a Docker image with a full JVM in it, wait for it to boot, configure stubs via a REST API or a pile of JSON files, then tear it down. For a Python project, that's a second language runtime in your pipeline purely to answer GET /users with a canned response.

Mimicker is a Python-native alternative. It's a plain pip install, it starts in-process or via a one-line CLI call, and it has no JVM, no native dependencies, and no heavy runtime — just two small pure-Python libraries (PyYAML for config, colorlog for output).

The Python DSL

from mimicker.mimicker import mimicker, get

mimicker(8080).routes(
    get("/hello").body({"message": "Hello, World!"}).status(200)
)
Enter fullscreen mode Exit fullscreen mode

That's a running mock server on port 8080. No config file, no separate process to manage if you don't want one.

The same thing in YAML

For when you want stubs defined outside your test code, useful if QA or frontend devs need to spin up a mock without touching Python:

# stubs.yaml
routes:
  - method: GET
    path: /hello
    status: 200
    body:
      message: Hello, World!
Enter fullscreen mode Exit fullscreen mode
mimicker serve --config stubs.yaml
Enter fullscreen mode Exit fullscreen mode

Where WireMock still wins

WireMock is mature, has a huge feature set (request matching on nearly anything, record-and-playback, fault injection, a proper admin API), and if you're already in a JVM shop, it's a known quantity. Mimicker doesn't try to match that surface area — it's intentionally smaller.

Where mimicker is a better fit

You're testing a Python service, you don't want a second runtime in CI, and you want stub definitions your whole team can read without learning WireMock's JSON mapping format.

Using it in CI

There's an official GitHub Action:

steps:
  - uses: actions/checkout@v4
  - uses: mimickerhq/mimicker-action@v1
    with:
      config: stubs/api.yaml
  - name: Run tests
    run: pytest
Enter fullscreen mode Exit fullscreen mode

It also ships something WireMock doesn't have out of the box: a stub coverage report. After your tests run, it tells you which stubs were actually hit, so if you delete an endpoint from the real API and forget to update the stub, you find out in CI instead of in production three weeks later.

- name: Mimicker coverage report
  if: always()
  run: bash ${{ steps.mock.outputs.report-script }}
Enter fullscreen mode Exit fullscreen mode

Add fail-on-unused: true and the job fails outright if a stub goes stale.

Try it

Mimicker is at github.com/mimickerhq/mimicker, docs at mimickerhq.github.io/mimicker. It's still small — if you try it and something's missing for your use case, that's exactly the kind of issue I want to hear about.

Top comments (0)