javahandlebars.jswiremockhandlebarshelper

WireMock is adding unexpected character when using CustomHelper


I am trying to use custom helpers to convert a list of Query Parameters form a request to a JSON response. The request is something like /scores?userIds=1&userIds=2 and my desired response is a list of JSON objects like the following:

[
  {
    "userId": 1,
    "score": 80
  },
  {
    "userId": 2,
    "score": 200
  }
]

To do so, I have implemented a helper called userScoreHelper:

Helper<List<String>> userScoreHelper = (context, options) -> {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("[");
    context.forEach(element ->
            stringBuilder
                    .append("{\"score\": ")
                    .append(RandomGeneratorUtility.generateRandomNumber(0, 700) - 1)
                    .append(",\"userId\": ")
                    .append(element)
                    .append("},")
    );
    stringBuilder
            .deleteCharAt(stringBuilder.lastIndexOf(","))
            .append("]");
    log.debug("Json response: {}", stringBuilder.toString());
    return stringBuilder.toString();
};

And then I registered the helper in my WireMockServer configuration as follows:

@Bean(initMethod = "start", destroyMethod = "stop")
@Rule
public WireMockServer mockServer() {
    return new WireMockServer(
            options()
                    .port(9561)
                    .extensions(new ResponseTemplateTransformer(false,
                            "user-score-helper",
                            userScoreHelper))
    );
}

The configuration of my stub looks like this:

public class ScoringCommunicatorMocks {
    public static void setupMockScoringCommunicatorResponse(WireMockServer mockService) {
        mockService.stubFor(
                WireMock.get(WireMock.urlPathEqualTo("/scores"))
                        .willReturn(WireMock.aResponse()
                                //Using the registered handlebars helper here
                                .withBody("{{user-score-helper request.query.userIds}}")
                                .withHeader("Content-Type", "application/json")
                                .withStatus(200)
                                .withTransformers("response-template"))
        );
    }
}

And the output of the helper is a valid JSON according to my debugging logs, something like this:

[{"score": 304,"userId": 10},{"score": 28,"userId": 20}]

But when I try to run my unit tests I am getting an error message from JSON Decoder stating that my response contains an unexpected '&' character.

feign.codec.DecodeException: JSON conversion problem: Unexpected character ('&' (code 38)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('&' (code 38)): was expecting double-quote to start field name
 at [Source: (PushbackInputStream); line: 1, column: 2] (through reference chain: java.util.ArrayList[0])

I suspect the WireMock is having problem with escaped " character because if I put the generated JSON object directly in the body like this .withBody("[{\"score\": 304,\"userId\": 10},{\"score\": 28,\"userId\": 20}]") it just works perfectly.

This is an awfully strange behavior and I have no clue how to get deeper at the root cause of this error (the rest of the stacktrace is irrelevant and adds nothing useful to what I have already stated here).

Any pointers or solutions are greatly appreciated.


Solution

  • I have actually managed to figure out what was wrong when I finished writing the question. It was indeed the the problem with escaping characters, all I needed to do was to use the "triple-mustaches" or "triple-stash" when I am calling the helper .withBody("{{{user-score-helper request.query.userIds}}}") instead of .withBody("{{user-score-helper request.query.userIds}}")