Is there a way to make sure that if provider chang...
# pact-jvm
a
Is there a way to make sure that if provider changes the name from
id
to
ids
the contract test would fail?
Copy code
{
  "id": "5",
  "type": "something"
}
I looked at .stringValue which only compares "5" and not
id
itself.
t
I'm not sure I understand your question. If you give pact this object, and the provider changes so that the field you are expecting (in this case
"id"
) is not there any more (which would happen if it was renamed) then the pact will fail. If it's not failing, there's something else going on
a
Yes, I did rename the field from
id
to
ids
in provider. Contract still passed. I tired using
.stringType("id", "5")
from
PactDslJsonBody
and
Copy code
object.stringType("id", "5");
from
LambdaDsl.newJsonBody;
still the test won't fail.
If I change the data type of id from String to int in provider with
.stringType("id", "5")
(from consumer) that it does fail.
t
Are you sure that the provider isn't returning the
id
property?
I'm not too familiar with the JVM DSL - can you share more of your test?
a
Let me check once again in debug mode for
context.verifyInteraction();
b
If the provider changes a field name (e.g.
id
to
ids
), the consumer test still won't fail, but the provider verification should.
t
Oh right! Yes, that's a good callout. The consumer test is setting up the expectations for the provider. It will only fail if: 1) Your client doesn't send the request you said it would 2) Your client didn't understand the response you said it would. If the client's expectations (recorded in the pact) don't match the provider, the verification will fail later on.
🙏 1
a
Yes, in my case consumer is asking for
id
in contract and provider renamed it to
ids
I am expecting the provider test to fail but it passes.
in
PactVerificationContext.kt
expectedResponse has
Copy code
status: 200
	headers: {Content-Type=[application/json]}
	matchers: MatchingRules(rules={body=Category(name=body, matchingRules={$.id=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@3bf0d1fb], ruleLogic=AND, cascaded=false), $.type=MatchingRuleGroup(rules=[au.com.dius.pact.core.model.matchingrules.TypeMatcher@3bf0d1fb], ruleLogic=AND, cascaded=false)})})
	generators: Generators(categories={})
	body: PRESENT({"id":"5","type":"House"})
actualResponse has
Copy code
ProviderResponse(statusCode=200, headers={Date=[Thu, 15 Sep 2022 ], Content-Type=[application/json], Transfer-Encoding=[chunked]}, contentType=application/json, body={"type":"House","id":"5"})
expect and actual both match in provider; that's why it's passing I think.
I have renamed all instances of
id
to
ids
tho 🤔
t
If you have renamed them all, then the question is why your actual response doesn't have the new name
are you mocking the actual response? (this is not a good idea)
It's using org.mockito.Mockito.when to mock
Is that not recommended?
b
nah, mocking the repository response in the provider verification is fine (*as long as it the repo shape isn't what ends up on the wire)
have you checked that the response from the provider is actually sending back what you expect? (outside of the test)
That's while test is running. How can I do it outside the test? Since it spins up a mock server
Making calls to mock server on given path in browser throws error
b
Right, that indicates that you haven't actually renamed it to
ids
everywhere. If the actual response (in & out of the test) returns
{"type":"House","id":"5"}
, then your controller is rendering out a class (or whatever) with
id
.
The provider verification doesn't start a mock server, it should start your provider 🤔
Without seeing the code, though, it's going to be hard to debug. If it's easy enough, the next step might be to link a repo that reproduces this issue.
a
I am using the workshop example from https://github.com/pact-foundation/pact-workshop-jvm-spring/ and renamed the id to ids in Product.java to try and fail the provider
If you debug (step into) on this line https://github.com/pact-foundation/pact-workshop-jvm-spring/blob/c642c739c49ff8543f05f0bcb517bd3529ba9a5e/provider/src/test/java/au/com/dius/pactworkshop/provider/ProductPactProviderTest.java#L55 It should have mock server url (localhost:port) and path is binded to compare actual response vs expected (from consumer)
I'll create a repo on GitHub and try to replicate this issue with some steps and share it here.
b
Which step do you have checked out?
a
Go all the way to step 11 and update id in Product.java and run provider test
Rename id to ids
b
Are you reaming the private field?
Pretty sure that won't work, you need to rename the getters/setters for
Response.of
to work in the controller.
Copy code
public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
a
b
The private member won't be used by Spring's conversion helper. Anyway, this isn't a Pact question anymore, it's about Java Beans & Spring.
Does it work if you rename
getId
to
getIds
?
a
Yes, It does fail the test now as expected. I though pact was caching somehow. Thank you 👍
👍 1
b
You should be able to confirm that it's not Pact by running the provider, and getting
id
in the response :)
🙏 1
a
appreciate your time helping me debug this. thank you
👍 1