Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug [V4] PactDslJsonRootValue as request body fails #1841

Open
huehnerlady opened this issue Nov 27, 2024 · 8 comments
Open

Bug [V4] PactDslJsonRootValue as request body fails #1841

huehnerlady opened this issue Nov 27, 2024 · 8 comments

Comments

@huehnerlady
Copy link
Contributor

My issue sounds a bit similar to #883, but this time it is with Pactversion V4.

I have the following pact test

@ExtendWith(value = [PactConsumerTestExt::class])
@Tag("pact")
@PactTestFor(providerName = "Provider")
class WebidStatusPactConsumerTest {

  @Pact(consumer = "Consumer")
  fun test(builder: PactBuilder) =
      builder
          .expectsToReceiveHttpInteraction("test") { httpBuilder ->
            httpBuilder
                .withRequest { httpRequestBuilder ->
                  httpRequestBuilder
                      .path("/test")
                      .method("POST")
                      .headers(mapOf("Content-Type" to "text/plain"))
                      .body(PactDslJsonRootValue.stringType("exampleString"))
                }
                .willRespondWith { httpResponseBuilder ->
                  httpResponseBuilder
                      .status(200)
                }
          }
          .toPact()

  @Test
  @PactTestFor(pactMethod = "test", pactVersion = V4)
  fun test(mockServer: MockServer) {
    shouldNotThrowAny {
      RestTemplate().postForObject<Void>(mockServer.getUrl() + "/test", "exampleString")
    }
  }
}

When this runs, I get the pact error

au.com.dius.pact.consumer.PactMismatchesException: The following mismatched requests occurred:
body - /: Expected body '"exampleString"' to match 'exampleString' using equality but did not match

when I change my request to be "\"exampleString\"" it works (I run into the next issue in my pact, but this is out of scope here)

So it seems there is an additional " expected for some reason?

@rholshausen
Copy link
Contributor

Couple things are odd about that test.

Firstly:
You are using a JSON DSL to build a plain text body. While this will not fail, it will create a proper JSON document.
I.e. body(PactDslJsonRootValue.stringType("exampleString")) will create well-formed JSON "exampleString" (note the quotes).

However, this line
RestTemplate().postForObject<Void>(mockServer.getUrl() + "/test", "exampleString")
has Void as the body type, so it will just create the request with the body from the string contents. I.e. no quotes.

Secondly:
You are using the stringType matching function on a plain text body. This makes no sense to do, as a plain text body can only have text content, so will never match anything other than a string.

@huehnerlady
Copy link
Contributor Author

@rholshausen thanks for your answer. what would then be the correct Body saying "the pact allows any string, but as an example it should be 'exampleString'"?

@rholshausen
Copy link
Contributor

A regex matcher is the only one that makes sense for a plain text body.

@huehnerlady
Copy link
Contributor Author

huehnerlady commented Dec 5, 2024

I tried

.body(regexp(".*", "exampleString"))

But this seems not to be allowed.

Then I tried PactDslJsonRootValue.stringMatcher(".*", "exampleString") and it works.

Is that what you were thinking of, or something else?
I just ask because it still uses the "Json" item, so I am a bit confused what the difference is. I thought basically stringtype(example: String) is basically stringMatcher(".*", example), but it seems not to be the case?

@huehnerlady
Copy link
Contributor Author

huehnerlady commented Dec 5, 2024

Also when I use the same mechanism on the response side I get the error even with the stringMatcher version

              .willRespondWith { httpResponseBuilder ->
                httpResponseBuilder
                    .status(201)
                    .header("Content-Type", TEXT_PLAIN_VALUE)
                    .body(PactDslJsonRootValue.stringMatcher(".*", "123456"))
              }

I get:


Generating response: HttpResponse(status=201, headers={Content-Type=[text/plain]}, body=PRESENT("123456"), matchingRules=MatchingRules(rules={body=MatchingRuleCategory(name=body, matchingRules={$=MatchingRuleGroup(rules=[RegexMatcher(regex=.*, example=123456)], ruleLogic=AND, cascaded=false)}), status=MatchingRuleCategory(name=status, matchingRules={}), header=MatchingRuleCategory(name=header, matchingRules={})}), generators=Generators(categories={}))

[...]

Expected :"123456"
Actual   :""123456""

@rholshausen
Copy link
Contributor

That's the correct way, but it looks like your provider is returning JSON encoded string as well.

@rholshausen
Copy link
Contributor

Or, on the response side, do you mean in your consumer test?

@huehnerlady
Copy link
Contributor Author

Hi, sorry for the confusion. This is all a consumer test. first I had the problem when I had a string body as a request parameter, and that I could fix. But then I now have a string parameter in the response body and I could not use the same fix here for some reason

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants