Hello all, I am new to WireMock and running into a...
# help
b
Hello all, I am new to WireMock and running into an issue. I am trying to write tests for a class that calls to an external API, and want to programmatically mock the API responses. This API has a design which isn't great (understatement), so all requests to it are GET requests with a single query parameter which contains a URLEncoded JSON object of fairly significant size. For the purposes of my tests there are only one or two fields I care about in the JSON so I can stub requests properly, so my intent is to create a custom RequestMatcher that URLDecodes the json object and then matches values in the JSON using a Map with String JsonPath keys and String values. To test the validity of this approach I've created a new Spring Boot service to test in, and have created the following Test:
Copy code
@SpringBootTest
class TestControllerTest {

    private WireMockServer wireMockServer;
    private CloseableHttpClient httpClient = HttpClients.createDefault();

    @BeforeEach
    void setUp() {
        wireMockServer = new WireMockServer(
                WireMockConfiguration.options()
                        .port(8081)
        );
        wireMockServer.start();
        WireMock.configureFor("localhost", 8081);
    }

    @AfterEach
    void tearDown() {
        wireMockServer.stop();
    }

    @Test
    void testParam() throws Exception {
        stubFor(
                get(
                    "/test"
                ).andMatching(new AtiRequestMatcher(Map.of("Test", "test")))
                .willReturn(
                    aResponse().withStatus(200).withBody("Successfully Mocked")
                )
        );
        HttpGet getRequest = new HttpGet("<http://localhost:8081/test>");
        CloseableHttpResponse httpResponse = httpClient.execute(getRequest);
        assertEquals(200, httpResponse.getCode());
        assertEquals("Successfully Mocked", EntityUtils.toString(httpResponse.getEntity()));
    }
}
As well as the following RequestMatcher (note: This is just to test that I have things wired together correctly, which I apparently don't):
Copy code
public class AtiRequestMatcher extends RequestMatcher {
    private final Map<String, String> parameters;

    public AtiRequestMatcher(Map<String, String> parameters) {
        this.parameters = parameters;
    }

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

    @Override
    public MatchResult match(Request request) {
        return MatchResult.of(true);
    }
}
When I run this, I am getting the following error:
Copy code
com.github.tomakehurst.wiremock.common.AdminException: Custom matchers can't be used when administering a remote WireMock server. Use WireMockRule.stubFor() or WireMockServer.stubFor() to administer the local instance.
For additional context, here are the dependencies I have on the project:
Copy code
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.4.2'
    id 'io.spring.dependency-management' version '1.1.7'
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    testImplementation 'org.wiremock:wiremock-standalone:3.11.0'
    testImplementation 'org.apache.httpcomponents.client5:httpclient5:5.4.2'
}
I'm at a loss for what I should be doing differently. Any suggestions?
t
The problem is that you’re trying to inline a Java custom matcher but using the static DSL which always goes over the network. There’s a simple fix however, which is to call the instance version of the DSL, so
wireMockServer.stubFor(…)
which will directly configure the stub in the server and can thus attach a bit of custom code.
b
I knew it had to be something silly I was missing. Thank you!
t
It’s not the most obvious thing unfortunately