Hey everyone, I'm currently thinking about how to ...
# general
t
Hey everyone, I'm currently thinking about how to deal with optional and nullable fields in our implementation of contract tests. Now, i've read the articles on why pact doesn't provide an optional operator (except from some JVM implementation?) and I get why. Nevertheless it feels a bit tedious having to define a separate request for the optional and non optional fields (especially because strictly speaking you would have to have a separate test for each layer of nested fields, as each field that is optional and an object may have optional fields itself). Surely, in some cases there are specific use cases that dictate which fields should or should not be set that could be adopted in the tests. But in many cases we have just data values that might not have been set yet. Sure I could follow defensive programming and just assume that any of these might be null, but I think it would then be hard to differentiate in which case to do one or the other. I thought about whether it would instead be possible to introduce a custom matcher
optional
that wraps around the matcher for the non-null value. The testing framework could then be modified to execute the test twice. Using some global state, the
optional
matcher would one time then provide the non null matcher and one time the nullish matcher or none at all. I was also thinking about using the test data builder pattern on the provider side, which might make it possible to use a similar approach on the provider side to generate Dto instances with either all values, or just the required ones. Is this approach in general in line with Pacts ideas and principles?
Did a PoC Implementation for an
optional
matcher with Pact JS, seems to be working quite well. Encountered that either the request or the state name needs to differ to include both interactions in the contract. Different state params are not sufficient. Problem is reported, but this might be intended.
b
Just back from a month of leave, so sorry for the late reply 🙂 The normal approach I'd recommend is to capture the distinct situations that are relevant (1 per contract scenario). The extended question (which varies a lot by different people's data modelling) is: do you have combinations of optional fields that are significant? If things go missing together, maybe they could be grouped into a single optional object. If not, maybe you don't need a scenario for when they
t
First of all, thanks for taking the time to still write a response. In fact I think in most cases we don't have many specific combinations of optional fields. > If not, maybe you don't need a scenario for when they're all missing, that could be covered by a unit test on the consumer. But how would I make sure, that the provider will only be able to set those to null then? As far as I understand, there is still nothing that (somewhat) guarantees that the fields assumed to be required by the client are actually always set by the provider. My current implementation for the approach described above doesn't strictly enforce this as well (as it cannot be assured that the
optional
switch is actually used on nullable fields without a linter or something similar), but at least it confronts the person writing the provider contract tests with the decision, whether a field should be nullable or not.
b
Yeah, if you want to use the contract to highlight that all the fields are allowed to be missing, then making a scenario that only has the minimum mandatory fields is a good idea. If different combinations of fields don't represent specific scenarios, then there's not much point capturing the permutations 👍
basically, anything not covered by the contract is "undefined" rather than valid or invalid . . . so you want to just add as much coverage as gives you confidence
t
Okay thanks. From what I'm seeing so far, the approach above seems to be working out. However, if I introduce a new optinal field, in practice it would be safe to deploy without provider implementation, but the tests would still fail, because the test where all fields are set requires the provider to be implemented. Would be the cherry on top in our (currently) non-CD process, but I guess it counts as desired behavior, as you shouldn't rely on the proposed field structure until the provider confirms that it's actually gonna be that way.
b
If you're getting to the point where you have the consumer side of the contract, but the provider side won't be ready for a while, then yes,
can-i-deploy
should fail. There are a few different approaches for dealing with that scenario, including pending & WIP pacts, and there was some discussion recently about a feature flag facility.