pact-net icon indicating copy to clipboard operation
pact-net copied to clipboard

Provider state parameters are serialised as numbers, causes errors in provider state middleware when using System.Text.Json

Open DavidJFowler opened this issue 2 years ago • 2 comments
trafficstars

If the value of a provider state parameter is a number string, it is serialised in the pact file as a number. This is an issue if the provider state middleware in the provider tests uses System.Text.Json to deserialise a ProviderState value as System.Text.Json does not deserialise non-string values into string properties. https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/migrate-from-newtonsoft?pivots=dotnet-6-0#non-string-values-for-string-properties.

For example:

using System.Net;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using PactNet;

var config = new PactConfig
{
    PactDir = Path.Join("..", "..", "..", "pacts"),
    DefaultJsonSettings = new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),

    }
};

var pact = Pact.V3("consumer", "provider", config).WithHttpInteractions();

pact.UponReceiving("A valid request")
    .Given("state with parameter", new Dictionary<string, string>() {["id"] = "10", ["name"] = "Fred"})
    .WithRequest(HttpMethod.Get, "/api/endpoint")
    .WillRespond()
    .WithStatus(HttpStatusCode.OK);

await pact.VerifyAsync(async ctx =>
{
    using var apiClient = new ApiClient(ctx.MockServerUri);

    await apiClient.TestRequestAsync();
});

public class ApiClient: IDisposable
{
    private readonly HttpClient _httpClient;

    public ApiClient(Uri baseUri)
    {
        _httpClient = new HttpClient { BaseAddress = baseUri };
    }

    public async Task TestRequestAsync()
    {
        await _httpClient.GetAsync("api/endpoint");
    }

    public void Dispose()
    {
        _httpClient.Dispose();
    }
}

generates this pact. Note that parameter "id" is serialised as 10 not "10".

{
  "consumer": {
    "name": "consumer"
  },
  "interactions": [
    {
      "description": "A valid request",
      "providerStates": [
        {
          "name": "state with parameter",
          "params": {
            "id": 10,
            "name": "Fred"
          }
        }
      ],
      "request": {
        "method": "GET",
        "path": "/api/endpoint"
      },
      "response": {
        "status": 200
      }
    }
  ],
  "metadata": {
    "pactRust": {
      "ffi": "0.4.0",
      "models": "1.0.4"
    },
    "pactSpecification": {
      "version": "3.0.0"
    }
  },
  "provider": {
    "name": "provider"
  }
}

DavidJFowler avatar Apr 06 '23 10:04 DavidJFowler

Thanks for the report 👍 I'll check out whether the problem is happening in PactNet itself or whether it's after we've passed to the FFI library.

If it's the latter, and gut feel is that it is, then I'll raise an issue on the other repo and link here.

adamrodger avatar Apr 06 '23 11:04 adamrodger

I've added a test which reproduces the issue, and confirms that this is an issue in pact-reference, not pact-net. We're passing a string value but a numeric value ends up getting written to the pact file.

I'll raise an upstream issue and link here.

adamrodger avatar Apr 09 '23 15:04 adamrodger

Unfortunately the upstream maintainers closed the linked issue I created to change this as they believe it's working as expected, and so there's nothing I can do to change this issue.

I've added a comment saying I don't agree that's working as expected, but that's where we are unfortunately.

adamrodger avatar May 27 '24 21:05 adamrodger

Added a comment here about a resolution from reading the linked issue, which appears to resolve the issue reproduction. (great things to have to hand!)

https://github.com/pact-foundation/pact-reference/issues/263#issuecomment-2134110690

YOU54F avatar May 27 '24 22:05 YOU54F

question - how would you expect someone to pass in an integer value here if the signatures are strings for end users?

YOU54F avatar May 27 '24 22:05 YOU54F

Unfortunately the upstream maintainers closed the linked issue I created to change this as they believe it's working as expected, and so there's nothing I can do to change this issue.

I've been reflecting on this overnight and I'm sorry you feel that there is nothing you can do to change this issue. I actually thought that when I read that comment that it was going to be something outside the Pact ecosystem, rather than from inside.

We definitely want to find the right, or most pragmatic solution, that works well for as many users, in as many consuming languages as possible!

Maybe the current direction isn't correct, but we are always happy to deliberate, and deliberate some more until we can get to a democratised solution :)

We are all part of one big (hopefully happy) family!

YOU54F avatar May 28 '24 11:05 YOU54F