Docs SDK Test Container (Go & Java)

Test Container (Go & Java)

Mockarty ships a programmatic test-container API so your tests can spin
up a fresh mock server per test (or per package) without managing the
Docker lifecycle by hand. It is the drop-in replacement for
wiremock-testcontainers (Java) and wiremockcontainer (Go) — point
your existing test bodies at the Mockarty container class and they keep
working, because the running image exposes the same WireMock
/__admin/* API plus Mockarty’s native admin API on the same port.

The container itself runs the real mockarty-cli mock serve process
baked into the mockarty/cli:<version>-mock Docker image. There is no
embedded engine — the test container behaves identically to a
production CLI install, just managed by your test runner.

When to use it

  • You have an existing WireMock testcontainer suite and want a one-line
    swap to Mockarty.
  • You want isolated mocks per CI shard or test package and prefer a
    programmatic API over a manually managed docker run.
  • You want to record traffic with a HAR file (recorder export, browser
    dev-tools, Mockarty Recorder) and replay it inside the same test.

Prerequisites

  • Docker reachable from the test process (the test harness skips
    cleanly when there is no daemon).
  • The image mockarty/cli:latest-mock available locally or via a
    registry your test environment can pull from.

Go quickstart

package mypkg_test

import (
    "context"
    "net/http"
    "testing"

    "github.com/mockarty/mockarty-go/mockartycontainer"
)

func TestMyAPI(t *testing.T) {
    ctx := context.Background()

    c := mockartycontainer.MustRun(ctx, t,
        mockartycontainer.WithImage("mockarty/cli:latest-mock"),
        mockartycontainer.WithMappings("./testdata/mocks"),
    )

    resp, err := http.Get(c.URL() + "/api/users/1")
    if err != nil { t.Fatal(err) }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        t.Fatalf("status = %d", resp.StatusCode)
    }
}

MustRun fails the test on any start error and registers a
t.Cleanup hook so the container is torn down automatically when the
test ends. If you prefer manual lifecycle management, call
mockartycontainer.Run(ctx, opts...) and defer container.Terminate(ctx).

Options

Option Effect
WithImage(ref) Override the container image (private registry, pinned digest).
WithFormat(f) Stub dialect: FormatAuto (default), FormatWireMock, FormatMockoon, FormatMockarty.
WithMappings(hostDir) Bind-mount a directory of stub files; loaded at startup.
WithHAR(hostFile) Bind-mount a HAR file; mocks are generated at startup.
WithStubFile(hostFile) Mount a single stub file. Repeatable.
WithPort(p) Pin the host TCP port. Use 0 (default) for ephemeral.
WithEnv(k, v) Inject an extra env-var into the container.
WithLogger(w) Stream the container’s stdout+stderr to a writer.
WithStartupTimeout(d) Bump the wait-for-ready deadline (default 60s).

Endpoint URLs

The container multiplexes three admin surfaces on the same listener:

Method URL Purpose
Catch-all c.URL() + "/<your-route>" Hit any mocked endpoint.
WireMock c.WireMockURL() + "/mappings" List, create, reset WireMock stubs.
Mockarty c.MockartyURL() + "/mocks" Native Mockarty admin API.
Health c.MetricsURL() + "/health" Liveness probe.

Runtime mock registration

err := c.AddWireMockStub(ctx, map[string]any{
    "request":  map[string]any{"method": "GET", "url": "/api/runtime"},
    "response": map[string]any{"status": 200, "body": `{"hi":"world"}`},
})

For native Mockarty mocks (multi-protocol, gRPC, MCP, Kafka context):

err := c.AddMockartyMock(ctx, mockartySDKMock)

To reset between assertions:

err := c.Reset(ctx)

HAR replay

c := mockartycontainer.MustRun(ctx, t,
    mockartycontainer.WithHAR("./testdata/traffic.har"),
)

The HAR file is mounted at /har/traffic.har and replayed at startup
via the MOCKARTY_HAR_REPLAY env-var; HAR-generated mocks are layered
on top of any WithMappings(...) stubs.

Java quickstart

import ru.mockarty.testcontainers.Format;
import ru.mockarty.testcontainers.MockartyContainer;

@Testcontainers
class MyApiTest {

    @Container
    static MockartyContainer mockarty = new MockartyContainer()
        .withFormat(Format.AUTO)
        .withMappingDirectory(Path.of("src/test/resources/mocks"))
        .withHarReplay(Path.of("src/test/resources/traffic.har"));

    @Test
    void hitsStub() throws Exception {
        HttpClient http = HttpClient.newHttpClient();
        HttpResponse<String> resp = http.send(
            HttpRequest.newBuilder(URI.create(mockarty.url() + "/api/users/1")).GET().build(),
            BodyHandlers.ofString());
        assertEquals(200, resp.statusCode());
    }
}

The Java module ships the MockartyContainerExtension JUnit5 extension
so plain field declarations work without @Testcontainers.

Direct docker run alternative

If you cannot use a programmatic container client, the same image is
runnable directly:

docker run --rm -p 8080:8080 -p 9090:9090 \
  -v "$(pwd)/mocks:/mocks:ro" \
  -e MOCKARTY_MOCK_DIR=/mocks \
  mockarty/cli:latest-mock

The two surfaces are equivalent — the test-container wrapper merely
manages the lifecycle for you.

Migrating from WireMock testcontainers

Before After
new WireMockContainer() new MockartyContainer()
.withMapping("name", ...) .withMappingDirectory(Path.of("..."))
WireMockContainer#getBaseUrl() MockartyContainer#url()
wm.resetMappings() mockarty.reset()
mockartycontainer.New(...) identical

WireMock JSON stubs are accepted verbatim — no rewrite required.

  • WireMock Migration Guide — server-side
    WireMock compatibility (use this when you already run Mockarty as a
    long-lived process and just want to talk to it from WireMock clients).
  • SDK Guide — the parent SDK reference.
  • CLI Container (Docker) — running the CLI
    image directly without testcontainers.