Skip to content

Make built-in test generator more customizable #2166

@TehMillhouse

Description

@TehMillhouse

Our Problem Context

We're maintaining a REST API across two completely separate backends. The backends have backend-specific extensions, so some JSON members only show up when running against one backend. We'd like to include those backend-specific extensions in our contract tests somehow, gated by which backend is currently being tested.

For context, we're using YAML contracts exclusively.

Proposed Solution

SingleTestGenerator already exists, but we'd have to copy-paste large swathes of spring-cloud-contract just to add one if to every generated assert. Providing a replacement for part of the built-in test generator via spring.factories almost works, if it weren't for the fact that many, many classes and interfaces in org.springframework.cloud.contract.verifier.builder are package-private, and thus can't be easily subclassed.

If the different parts of the built-in test generator (i.e. ClassBodyBuilder, BlockBuilder, SingleMethodBuilder, etc.) were public, we could sub them in and patch them in situ.

Pros:

  • Does not require costly re-engineering of the test generation logic
  • Greatly enhances customizability
  • The fact you still need spring.factories to get it to work imo accurately messages that this is still kind of a hack

Cons:

  • It's still kind of a hack
  • Replacing just part of some internal API is prone to breakage
  • Has the danger of becoming an eternally temporary solution

Related issues

I found #481 from 8 years ago, which was closed due to inactivity.
This could also kinda, sorta be used to fill the same need as #2153, at least in that it enables library users to work around the limitations themselves.

Alternatives considered

Our root need is to be able to hook into test generation more. I also quickly looked into registering a custom parser for contracts (so I can just discard the parts of the contract that aren't relevant for the currently selected backend), but I couldn't find a way to do this.

I could get something akin to this by simply duplicating all our contracts, putting them in different folders, and only every executing the test in the right folders for the current backend, but this would quickly lead to diverging contracts between the actively developed backends.

I could also implement SingleTestGenerator as it exists now, though this would mean copy-pasting about two-dozen internal classes, just to add probably one if in one bespoke location somewhere.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions