surpher/PactSwift

Question: Create PACT for JSON body that contains only a string

twwd opened this issue ยท 4 comments

twwd commented

โ” Question

How can we generate the PACT JSON file so that it contains a quoted string a body (e.g. "body": "\"EXPIRED\"")?

๐Ÿ’ฌ Context

We want to write a PACT consumer test for a back-end API that returns only a single string as response, e.g.

"EXPIRED"

In our consumer, we write

.willRespondWith(status: 410,
                        headers: [HttpHeaders.contentType: "application/json"],
                        body: Matcher.EqualTo("\"EXPIRED\"")

that leads to a successful execution of our test with the client but generates the wrong JSON for that is published to the PACT broker:

Expected

"response": {
        "body": "\"EXPIRED\"",
        "headers": {
          "Content-Type": "application/json"
        },
        "matchingRules": {
          "body": {
            "$": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "equality"
                }
              ]
            }
          }
        },
        "status": 410
      }

Actual

"response": {
        "body": "EXPIRED",
        "headers": {
          "Content-Type": "application/json"
        },
        "matchingRules": {
          "body": {
            "$": {
              "combine": "AND",
              "matchers": [
                {
                  "match": "equality"
                }
              ]
            }
          }
        },
        "status": 410
      }

Since there seems to be an ambiguity in the PACT specification regarding JSON string bodies. If the body is only a string, it is not interpreted as JSON like for objects and arrays but as plain text that is passed to the PACT provider test. Thus, the provider cannot parse the body EXPIRED since it is not valid JSON.

This seems to be a problem in pact-ffi. I've ran the same code you've shared and enabled all logging. PactSwift sends the following Pact data to pact-ffi:

{"metadata":{"pactSpecification":{"version":"3.0.0"},"pactSwift":{"version":"0.12.0"}},
"interactions":[{"response":{"status":200,"body":"\"EXPIRED\""},"providerState":"elements exist","request":{"path":"\/elements","method":"get"},
"description":"Request for a list"}],"provider":{"name":"unit-test-api-provider"},
"consumer":{"name":"pactswift-unit-tests"}}

Will pass this on to pact-ffi team. Thanks for reporting it.

What possible values are you expecting? Could you use another matcher? Maybe OneOf? It uses a regex as a base and sets the Pact with " around your expected string:

Nevermind... Still have holiday brain ๐Ÿคทโ€โ™‚๏ธ

As per pact-foundation/pact-reference#193 (comment) the content type is being set to JSON.
Try setting text/plain fore the response's content type instead?

Closing due to no activity on this matter.