Hello, I hope this message finds you well. I obse...
# pact-jvm
j
Hello, I hope this message finds you well. I observing a weird behaviour and I am not sure what I doing wrong. I am using
Copy code
testImplementation('au.com.dius.pact:consumer:4.3.9')
testImplementation('au.com.dius.pact.consumer:junit:4.3.9'
And creating two interactions for the same consumer and provider (one POST and other PUT). I am setting the same response header for both of the interactions but the second interaction, the
response.headers
are being generated different from what I am setting it. I am setting
responseHeaders.put("Content-Type", "application/json; charset=utf-8");
. The first interaction, the header is
"Content-Type": "application/json; charset=utf-8",
but in the second it is
"Content-Type": "application/json;charset=utf-8"
the difference being that the second there is no space after the
;
. I added another header just for testing and in the second interaction it added an
=
at the end. Basically, I want that the space in
"application/json; charset=utf-8"
is not removed in second interaction. Do you what can I do to achieve this? I am not sure if I am doing something wrong or is some kind of bug. (code and image in the thread)
This is the code that generates the contract file
Copy code
@Pact(consumer = "config-api", provider = "file-service")
    public RequestResponsePact createFileFragment(PactDslWithProvider builder)
    {
        Map<String, String> requestHeaders = createRequestHeaders();
        Map<String, String> responseHeaders = createResponseHeaders();

        PactDslJsonBody requestBody = new PactDslJsonBody()
                .uuid("clientId", "2454ad95-0352-4494-9a40-6afb333959e4");

        PactDslJsonBody responseBody = new PactDslJsonBody()
                .uuid("clientId", "2454ad95-0352-4494-9a40-6afb333959e4");
        return builder
                .given("a file does not exists")
                .uponReceiving("create file")
                .method("POST").headers(requestHeaders).body(requestBody)
                .matchPath("/files")
                .willRespondWith()
                .status(201).headers(responseHeaders).body(responseBody)
                .toPact();
    }

    @Pact(consumer = "config-api", provider = "file-service")
    public RequestResponsePact updateFileFragment(PactDslWithProvider builder)
    {
        Map<String, String> requestHeaders = createRequestHeaders();
        Map<String, String> responseHeaders = createResponseHeaders();

        PactDslJsonBody requestBody = new PactDslJsonBody()
                .uuid("clientId", "2454ad95-0352-4494-9a40-6afb333959e4");

        PactDslJsonBody responseBody = new PactDslJsonBody()
                .uuid("clientId", "2454ad95-0352-4494-9a40-6afb333959e4");

        String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";

        return builder.given("a file exists").
                uponReceiving("update the file")
                .method("PUT").headers(requestHeaders).body(requestBody)
                .matchPath("/files/" + uuidRegex)
                .willRespondWith()
                .status(200).headers(responseHeaders).body(responseBody)
                .toPact();
    }

    private Map<String, String> createResponseHeaders()
    {
        Map<String, String> responseHeaders = new HashMap<>();
        responseHeaders.put("Content-Type", "application/json; charset=utf-8");
        responseHeaders.put("X-Type", "test1; test2");

        return responseHeaders;
    }

    private Map<String, String> createRequestHeaders()
    {
        Map<String, String> requestHeaders = new HashMap<>();
        requestHeaders.put("Content-Type", "application/json");

        return requestHeaders;
    }
and this is the contract file
notice the
response.headers
difference in the second interaction (removes the spaces, and added an
=
)
I removed POST from the test and left only the PUT and then it generates it correctly. It seems to happen in the second interaction (have not tried with more than 2)
t
I can't help with your question, but I can tell you that both those headers should be treated the same - see https://httpwg.org/specs/rfc7231.html#media.type
☝️ 1
j
Interesting @Timothy Jones. I thought about that, but was not sure. My question is because I am getting this error on the provider verification
Expected header "Content-Type" to equal "application/json;charset=utf-8", but was "application/json; charset=utf-8"
. My provider is running on node with the
"@pact-foundation/pact": "^9.17.3"
. I thought the problem was in the consumer, but seems to be in the provider as it should(?) consider both values the same.
m
My guess is that you are generating a pact file with version
3
as the specification, but Pact JS core (the version you linked) only supports 2. I’m not sure if you downcast the consumer test to explicitly produce a v2 pact if that will fix it
I believe in V3, the way headers are managed differs slightly, so this could be the cause
If that doesn’t solve it, I’d add a regex matcher for the header. This way, the space can be made to be irrelevant
t
If that error is coming from pact, it is definitely a bug.
The http headers are well defined, and those two examples are defined to be equivalent
Matt's suggestion of the regex matcher would be a good workaround in the meantime
j
@Matt (pactflow.io / pact-js / pact-go), it was
V3
but changed the consumer generation to
V2
and it generated the same thing as before, where the second interaction had a different header value without the space .
I will try the regex matcher. Thank you very much for the help and the suggestion fistbump
Where should I open an issue? in pact-js repo?
t
Whichever pact framework is throwing the error
Pact js will just believe what you tell it about the header - I would guess that both your test and your client code are actually generating those two headers
m
So for clarity, the pact file looks to have the correct assertions in it now (one with and another without the additional space)
The ruby verifier I think will check those values verbatim (i.e. it will look at the space or lack thereof and check). So your provider should align with this if you want it to exact match
what behaviour are you now seeing with the new pact file?
j
It should have the two with spaces, as it is being set the same way. The same function sets the headers for the two interactions, but when it generates the contract file, one has no spaces
m
ah, I see
that is not a bug in Pact JS then. That sounds like a bug in Pact JVM
or a feature, as Tim suggested, it might be looking at what your client actually sends
t
Is the client actually sending different things?
m
that would be good to know
t
I think the client must be sending a different thing
m
@uglyog any ideas as to how that could be? Do the headers that were in the test get updated with what the client actually sends?
j
just to clarify @Timothy Jones, when you say client, you say the provider method being tested?
The thing is related to having two interactions. If I leave only the PUT (that has no space now) it generates the contract the way it was suppose to (with the space)
But If I leave the two, the second interaction always generates without the space, even having the same method on the definition.
u
Pact-JVM and Pact-Rust will parse those headers as per the RFC and compare the various parts. Spaces will be ignored unless they are in places that are important.
🙌 1
As to why it is occurring, that will need to be investigated, but it is a deficiency in the Ruby engine to compare them as strings. I agree it is not worth the effort and a regex can solve it
👍 1
t
No, I mean the consumer method being tested. The pact file is only written if the test passes and the consumer sends what you set up in the expectation. I'm guessing, but maybe the consumer is sending one without space and one with and maybe that's what is written in the pact. But I have no idea
I think Ron’s point is solid- just put in a regex and forget (although it would be good to track the bug regardless)
j
I don’t think that the method is one without space and other with, as if leave only the method that has no space (and comment out the other) it generates as expected (with spaces). I will use your regex matcher recommendation and will create the issues in the respective projects. Thank you so much for the help and for maintaining this amazing framework ❤️. I am a pact advocate at the company that I work for
❤️ 1
t
You're welcome! I'm no longer a maintainer, just here to help (the others totally are still maintainers, though)