Search code examples
javaokhttpweb-api-testingmockserver

MockServer headers expectations are too strict


I am trying to unit test a class whose main function is to make a REST client call. To invoke the REST api I am making use of OkHttp3 library.

var apiClient = new OkHttpClient().newBuilder().build();

var request = new Request.Builder()
        .url(myApiUrl)
        .method("GET", null)
        .addHeader("Content-Type", APPLICATION_JSON_VALUE)
        .addHeader("x-env", "DEV")
        .addHeader("apikey", "API-KEY")
        .build();

Google took me to MockServer framework which seems to be exactly what I want. So inside my test case I set the following expectation:

    mockServerClient.when(
            request()
                    .withMethod("GET").withPath("myApyUrl")
                    .withHeaders(
                        header("Content-Type", APPLICATION_JSON_VALUE),
                        header("x-env", "DEV"),
                        header("apikey", "API-KEY")
                    )
    ).respond(
            response()
                    .withStatusCode(200)
                    .withContentType(MediaType.APPLICATION_JSON)
                    .withBody("some response body")
    );

When I run the test I get a failure with the expectation I set as the reason:

method matched
path matched
body matched
headers didn't match

This is followed by a no expectation for which contains a lot more headers than the one I expected. This in my view is true as I only wanted to test for the headers I am explicitly set and of course the request will have more than that.

I am quite sure what I am trying to test is a normal scenario and thee reason for the failure is that somehow I am "too strict" forcing MockServer to test all headers rather than the one I set/expect.

Being very new with MockServerI just tried to google but I could not spot a clear way to solve my problem.

Thank you in advance for your inputs.


Solution

  • If I understand your problem correctly, then you want to mock a response for a given request, and the actual request contains more headers than what you've set up the mock server to expect.

    What you can do, if you know all the header keys, but not the values, is to simply ignore the value, as done below.

    // Example of setting up the ClientAndServer to ignore header values
    mockServer.when(request()
            .withMethod("GET")
            .withPath("/path")
            .withHeader("x-app-id", "id") // <- exact match
            .withHeader("x-api-key", "key") <- exact match
    
            // Ignore value of the two headers below
            .withHeader(NottableOptionalString.optional("x-transaktions-id"))
            .withHeader(NottableOptionalString.optional("x-request-id")))
        .respond(response()
            .withBody(someContent)
            .withStatusCode(200));