Skip to main content

Extending the WireMock Runner

The behaviour of the WireMock Runner’s serve mode can be extended in the same way as WireMock OSS, allowing custom request matching, filtering, and response transforming, to name a few of the available capabilities. The WireMock Runner supports all the available OSS extension points, allowing you to lift and shift your existing extensions directly into the Runner without any code changes.

Usage

Extensions are loaded into the WireMock Runner on startup via Java’s service loader framework. To execute your custom extensions in the WireMock Runner, compile your extension code into one or more .jar files and place these files into an extensions directory inside your .wiremock directory. Each extension must have a relevant entry in its jar’s extension service file. For example, if your jar file contains a RequestFilterV2 extension whose qualified class name is com.example.MyRequestFilter, the jar’s /META-INF/services/com.github.tomakehurst.wiremock.extension.Extension file must contain the entry com.example.MyRequestFilter. If your extensions are configured via an ExtensionFactory, these can be loaded into the Runner by placing the qualified name of the factory into the jar’s /META-INF/services/com.github.tomakehurst.wiremock.extension.ExtensionFactory file.

Examples

As a simple example to demonstrate loading extensions into the Runner, we’ll create an extension that will count how many requests have been made to a service, and another extension to report that number via a custom admin API endpoint. Here is all the code required for the extensions:
RequestCountingAdminApiExtensionFactory.java
package com.example;

import com.github.tomakehurst.wiremock.admin.Router;
import com.github.tomakehurst.wiremock.extension.AdminApiExtension;
import com.github.tomakehurst.wiremock.extension.Extension;
import com.github.tomakehurst.wiremock.extension.ExtensionFactory;
import com.github.tomakehurst.wiremock.extension.Parameters;
import com.github.tomakehurst.wiremock.extension.ServeEventListener;
import com.github.tomakehurst.wiremock.extension.WireMockServices;
import com.github.tomakehurst.wiremock.http.Body;
import com.github.tomakehurst.wiremock.http.RequestMethod;
import com.github.tomakehurst.wiremock.http.ResponseDefinition;
import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class RequestCountingAdminApiExtensionFactory implements ExtensionFactory {
    @Override
    public List<Extension> create(WireMockServices services) {
        var count = new AtomicInteger(0);
        return List.of(new RequestCountingAdminApi(count), new RequestCounter(count));
    }

    static class RequestCounter implements ServeEventListener {
        private final AtomicInteger count;

        public RequestCounter(AtomicInteger count) {
            this.count = count;
        }

        @Override
        public String getName() {
            return "request-counter";
        }

        public void afterComplete(ServeEvent serveEvent, Parameters parameters) {
            count.incrementAndGet();
        }
    }

    static class RequestCountingAdminApi implements AdminApiExtension {
        private final AtomicInteger count;

        public RequestCountingAdminApi(AtomicInteger count) {
            this.count = count;
        }

        public String getName() {
            return "request-counting-admin-api";
        }

        @Override
        public void contributeAdminApiRoutes(Router router) {
            router.add(RequestMethod.GET, "/request-count", (admin, serveEvent, pathParams) ->
                    new ResponseDefinition.Builder().setStatus(200).setBody(new Body(Integer.toString(count.get()))).build());
        }
    }
}
Place this code into a file in your working directory, along with a META-INF/services/com.github.tomakehurst.wiremock.extension.ExtensionFactory file with the following content:
com.example.RequestCountingAdminApiExtensionFactory
These files can be compiled to a jar file using the following commands:
javac -d . -cp <WIREMOCK_CORE_CLASSPATH_FILES...> RequestCountingAdminApiExtensionFactory.java
jar cf request-counting.jar com META-INF
The simplest way to obtain the appropriate WireMock core classpath files is to download the WireMock OSS standalone jar from the Maven Central repository.
For simplicity, this example uses off-the-shelf java* commands to compile a jar, but most extension projects will use a build tool like Gradle or Maven to generate the appropriate jar file(s). Examples of extension projects that use Gradle and Maven build tools are the WireMock JWT extension and the WireMock GraphQL extension. Once you have your jar file, place it in an extensions directory inside your .wiremock directory. Now start up the Runner in serve mode and make some requests to your services. Each service should now expose a custom admin API endpoint at GET /__admin/request-count that returns the number of requests that service has received.
curl http://localhost:8080/things/1
curl http://localhost:8080/things/2
curl http://localhost:8080/things/3

curl http://localhost:8080/__admin/request-count
3

Classpath isolation

Note that extension classes are loaded in an isolated fashion, meaning they do not have access to any classes not explicitly supplied in the extensions directory, with the exception of the WireMock core classes. Thus, if your extensions depend on Jackson for example, the appropriate Jackson jars must be supplied in the extensions directory. If WireMock core classes are supplied in the extensions directory, these will be ignored in favour of the WireMock core classes supplied by the Runner.