WireMock.Net icon indicating copy to clipboard operation
WireMock.Net copied to clipboard

Response Templating complex objects

Open dotnetprofessional opened this issue 1 month ago • 2 comments

I'm trying to get templating working, taking data from the incoming request and mapping it to the response. I'm sure I'm not understanding the examples as I just can't get anything but a very simple {{request.path}} to work. So at least I know its transforming :)

Any advice on how to map complex objects would be helpful. I tried looking at the samples, but none seemed to cover this scenario. They dealt with collections. I'm also confused with when to use body or bodyAsJson, the samples use body but the request is json. I've tried both without success. I get this is using the JsonPath syntax, but from what I can tell the syntax I have should work.

Here is a sample, that returns the error:

{"Status":"Value cannot be null. (Parameter 'value')"}

formatted request body:

{
  "PricingContext": {
    "Market": "USA"
  }
}
        var requestJson = JsonConvert.SerializeObject(new { PricingContext = new { Market = "USA" } });
        var responseJson = JsonConvert.SerializeObject(new { Market = "{{JsonPath.SelectToken request.body \"$.pricingContext.market\"}}" });
        var _wireMockServer = Server.WireMockServer.Start(new WireMockServerSettings
        {
            Port = 9091,
            AllowPartialMapping = true,
        });
        _wireMockServer
            .Given(WireMock.RequestBuilders.Request.Create()
                    .WithPath("/pricing")
                    .WithBody(requestJson)
                    .UsingPost())
                .RespondWith(Response.Create()
                    .WithHeader("Content-Type", "application/json")
                    .WithBody(responseJson)
                    .WithTransformer(true)
                );
        var http = new HttpClient();
        var response = await http.GetAsync($"{_wireMockServer.Url}/pricing");
        var value = await response.Content.ReadAsStringAsync();

dotnetprofessional avatar May 23 '24 02:05 dotnetprofessional

Did you try using BodyAsJson.

        var request = new { PricingContext = new { Market = "USA" } };
        var response = new { Market = "{{JsonPath.SelectToken request.bodyAsJson \"$.pricingContext.market\"}}" };
        var _wireMockServer = Server.WireMockServer.Start(new WireMockServerSettings
        {
            Port = 9091,
            AllowPartialMapping = true,
        });
        _wireMockServer
            .Given(WireMock.RequestBuilders.Request.Create()
                    .WithPath("/pricing")
                    .WithBodyAsJson(request)
                    .UsingPost())
                .RespondWith(Response.Create()
                    .WithHeader("Content-Type", "application/json")
                    .WithBodyAsJson(response)
                    .WithTransformer(true)
                );
        var http = new HttpClient();
        var response = await http.GetAsync($"{_wireMockServer.Url}/pricing");
        var value = await response.Content.ReadAsStringAsync();

StefH avatar May 23 '24 05:05 StefH

Yeah, but I'm actually wanting to have this work with the .json files in the final solution. However, I've included this sample as it seems to have the same issue, so assuming its not specific to using .json files.

So I did update the code to use .WithBodyAsJson rather than .WithBody and I'm getting the same result. You should be able to paste the code above into your test project (that's what I'm doing) and validate the error.

dotnetprofessional avatar May 23 '24 19:05 dotnetprofessional

When you use .WithBody(requestJson), the requestJson is just a string, it's not possible to do any JsonPath.SelectToken on a string.

In your case you could try: 1:

var requestJson = @"{ 'Name': 'John Doe', 'Age': 30 }"; // read json file
var request = JObject.Parse(requestJson);

2: And use .WithBodyAsJson(request)

StefH avatar May 24 '24 05:05 StefH