Search code examples
kotlinwiremock

Catch query param in WireMock stubbing and return it


In my kotlin app I have an endpoint GET /v1/money?accounts=... where accounts is a list with comma separated strings. I need to build a Wiremock stubbing where I'll return that list in the response. But my variant doesn't work:

portalWiremock.server().stubFor(
            get(urlPathMatching("/v1/money?accounts=.*"))
                .willReturn(
                    okJson(
                        """
                {
                    "trackingId": "abcde12345",
                    "accounts": ${'$'}{accountsList(request.queryParameter("accounts"))}
                }
                """.trimIndent()
                    )
                )
        )
...

fun accountsList(accountsParam: String?): String {
        val accounts = accountsParam?.split(",") ?: emptyList()
        val accountsJson = accounts.joinToString(",", "[", "]") { "\"$it\"" }
        return accountsJson
    }

Is there another way I should use? Is it possible in general to catch/return in that way?


Solution

  • When you are creating WireMock templated responses everything needs to be done within the template using the available handlebars helpers. Handlebars is the templating language used by WireMock to provide dynamic repsonses. When the template is rendered it won't know anything about the kotlin functions within your test so won't be able to call out to them.

    From what I can tell from your kotlin code, you are trying to take the comma separated values from the query parameter and return them as a json array in the response template.

    This means we are going to have to create that json array within the template itself. We can do this with a little bit of string manipulation:

    {{#assign 'accountsJson'}}[ "{{replace request.query.accounts ',' '","'}}" ]{{/assign}}
    {
       "trackingId": "abcde12345",
       "accounts": {{accountsJson}}
    }
    

    Then for a request like the following:

    /v1/money?accounts=one,two,tree,four
    

    We should see the following response:

    {
        "trackingId": "abcde12345",
        "accounts": [ "one","two","tree","four" ]
    }
    

    The template takes the query parameter one,two,tree,four and replaces every , with "," and then wraps the whole thing in a [" and "] to generate a valid json array. We then output that array in the correct part of the response json.

    To make this work with your example, you will need to enable response templating for the stub you are creating. An example of that can be found here - https://wiremock.org/docs/response-templating/#java

    You basically need to add .withTransformers("response-template") to the response in the stub.

    This would have been much nicer if there was a split function in the handlebars helpers but I couldn't find one. I will look at adding a feature request.