Stubbing and classpath isolation

Two additions to the mock server for when the verified-Mock() style does not fit: declarative stubbing (script responses, no verification) and classpath isolation (run the mock server inside a full application’s test suite).

Declarative stubbing

MockServer.startStubbing(…​) starts a server backed by its own StubbingHttpHandler — the Restito-style alternative to a Spock/Mockito mock handler. Register request→response stubs fluently via handler():

try (var server = MockServer.startStubbing()) {
    server.handler().when(HttpMethod.GET, "/widgets/42")
        .returns(HttpStatus.OK, Map.of("id", "42", "name", "Anvil"));
    server.handler().when(HttpMethod.GET, "/widgets")
        .query("category", "tools")
        .returns(HttpStatus.OK, List.of(Map.of("id", "42")));
    server.handler().when(HttpMethod.POST, "/token")
        .contentType("application/problem+json")
        .returns(HttpStatus.BAD_REQUEST, Map.of("error", "invalid_grant"));
    // point the client-under-test at server.url()
}

Matching and response rules:

  • A stub matches on the verb plus a path contains check; .query(name, value) adds required query params.

  • The last matching stub wins — a test can override a stub registered in shared setup.

  • An unmatched request gets a logged 404.

  • A Map/POJO body is serialized to JSON; .contentType(…​) overrides the response media type.

  • handler().clear() drops all stubs — for resetting between tests on a shared server.

There is no verification: assert on your client’s observable result, not on what the server received. When you need to assert the outbound request, use a Mock() handler as described in Mock server for client tests.

Classpath isolation

Starting a MockServer inside a full application’s test classpath (an in-application integration suite) normally boots a Micronaut context that discovers all the application’s beans — controllers, filters, StartupEvent listeners. MockServerOptions.isolated() narrows bean discovery to the core HTTP-server framework plus the mock server itself, so none of that runs:

var server = MockServer.startStubbing(MockServerOptions.isolated());

Only Micronaut’s META-INF/micronaut/ bean-definition discovery is filtered (by jar name, against an allow-list); class loading is untouched, so all classes still resolve normally. The default allow-list (MockServerOptions.DEFAULT_ISOLATION_ALLOW_LIST) covers Micronaut core, the Netty HTTP server, and the Jackson JSON stack. If your server needs another framework module discovered — a different JSON layer, a reactive bridge — add its jar-name marker instead of editing the library:

var server = MockServer.startStubbing(MockServerOptions.isolated().allow("micronaut-serde"));

Options

MockServerOptions also carries what the start(…​) overloads accept, fluently:

  • .environment("api", …​) — extra Micronaut environments alongside test and mock-http-server.

  • .property(key, value) / .properties(map) — context properties for the mock server’s own configuration.

Both startStubbing(options) and start(handler, options) take it, so isolation and stubbing combine freely with a hand-supplied handler.