Closed DavidOpDeBeeck closed 6 years ago
We had a chat with @dsyer and we came to the conclusion that you should go with the Multiple definitions
approach.
If that's not fully satisfactory you can turn off the default JAR generation (https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/pom.xml#L30) and generate a JAR with stubs yourself (https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/pom.xml#L102-L119). You can add the POJOs to that stub (https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/producer_with_restdocs/src/assembly/stub.xml#L11-L24). That way you can then add the stub as a test dependency you will have the POJO on the consumer / producer side (https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/master/consumer_with_restdocs/pom.xml#L46-L58).
Does it make sense? If you have any ideas how to improve this process then we'll be very happy with the feedback.
Thanks for the quick response!
If I understand your second paragraph correctly you propose a shared library between the producer, consumer and contracts projects? This library would then contain all the shared classes (in the example above the Gender.java
class)?
We specifically chose not to create such shared library, one of the reasons was that the maintainability of this library would increase and cause problems in the long run. This decision was made by taking the usage of the consumer service and previous experiences into account.
To get back to the Multiple definitions
approach. My opinion would be that this behavior should be supported / implemented by the plugin (without manually looping over all the enum values).
Making such a feature in the plugin would be complex. We would have to analyze the body (which we already do) and check if there are enums there. Then, we would have to store this information and do a combination of possibilities. I'd prefer not to touch the JSON parsing functionality cause it's already very complex. This feature would make it unsupportable IMO.
I think that a good compromise would be to go with Multiple definitions
. From the user perspective, it's trivial to make such a combination, cause the user knows which of the elements are enums.
Problem
A contract definition currently does not provide a way to easily enforce the existence of all the values of an enum at the producer side. This is necessary, because it is important that the enum values remain synchronized between the producer and the consumer.
Example
The example below defines an application that contains a producer that provides an API to create a person and a consumer that will consume this person creation API.
Application
Context
The application consists of 3 independent projects:
Class location
Producer
Contract
Regex
We can use a regex
$(regex('(MALE|FEMALE|UNKNOWN)'))
to allow for all the gender enum values, but only 1 will be selected at random for the producer test. This limitation doesn't enforce that all the enum values have to exist on the producer side.Multiple definitions
We could automate the creation of the contract above by creating a contract for each enum value. This ensures that the producer supports all the gender enum values. The disadvantage of this approach is that this becomes a mess when working with multiple enums in the same request body.
Do it yourself
We could also solve this problem by writing our own tests comparing the enum values with the enum values from the contracts.
Producer
Consumer
Conclusion
Maybe I'm missing some feature that Spring Cloud Contract provides to solve this problem, because I'm not entirely happy with any of the above solution.