Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about testing request/async response #2069

Open
cer opened this issue Dec 16, 2023 · 7 comments
Open

Question about testing request/async response #2069

cer opened this issue Dec 16, 2023 · 7 comments

Comments

@cer
Copy link

cer commented Dec 16, 2023

Request/async response is similar to HTTP except that it's message-based:

  • Client sends an command message to the service
  • Service sends back a reply message

The service owns the schema of the request and reply messages.

Older versions of Spring Cloud Contract supported request/async response fairly easily. See ConfirmCreateTicket.groovy.
The contract had input and output messages.

But, as far as I can figure out, in the more recent versions of Spring Cloud Contract, a contract for a message consists of an input/triggeredBy trigger and an output message.
Consequently, there are separate contracts for the request and reply messages.

From Spring Cloud Contract's perspective, the service is a producer of a replies and a consumer of requests.
The service/producer-side tests consist of

  • Code generated tests for the reply contracts
  • Stub runner tests for the service's request (not the client's) contracts

Similarly, from Spring Cloud Contract's perspective, the client is a producer of requests and a consumer of replies.
The consumer-side tests consist of

  • Code generated tests (from the provider/service contracts - not its own contracts) for the request contracts
  • Stub runner tests for the service's reply contracts

This is doable but a bit awkward.

One notable challenge, however, is that the consumer-side needs to have code generated tests for every service that it invokes asynchronously (as well as its own contracts).

Thoughts?

@marcingrzejszczak
Copy link
Contributor

Hey Chris!

We came to the conclusion that the input / output case is indeed a set of two scenarios.

  • triggered by code, produced output message - producer side (service A)
    • uses stub runner to consume the message (service B)
  • triggered by code, produced output message - producer side (service B)
    • uses stub runner to consume the message (service A)

Service A produces, service B consumes. Service B produces, service A consumes.

From the point of view of supporting the framework we've decided to limit to this one particular case (code triggers message) because supporting the code to generate all the fake routing mechanisms and fake listener creation was super hard to maintain with a lot of different edge cases.

One notable challenge, however, is that the consumer-side needs to have code generated tests for every service that it invokes asynchronously (as well as its own contracts).

Correct, the output side that was previously in the input / output now must be moved as a contract on the consumer side.

@cer
Copy link
Author

cer commented Dec 18, 2023

From the point of view of supporting the framework we've decided to limit to this one particular case (code triggers message) because supporting the code to generate all the fake routing mechanisms and fake listener creation was super hard to maintain with a lot of different edge cases.

Interesting. This appear straightforward with Eventuate but I guess supporting multiple brokers could get tricky.

@cer
Copy link
Author

cer commented Dec 18, 2023

One notable challenge, however, is that the consumer-side needs to have code generated tests for every service that it invokes asynchronously (as well as its own contracts).

Correct, the output side that was previously in the input / output now must be moved as a contract on the consumer side.

Key question: how to code generate for multiple dependencies + the service. AFAIK The verifier plugin appears to only support code generating from a single contracts JAR/dependency.

@marcingrzejszczak
Copy link
Contributor

Key question: how to code generate for multiple dependencies + the service. AFAIK The verifier plugin appears to only support code generating from a single contracts JAR/dependency.

Yeah, we don't really support that. The only thing that comes to my mind is to make the group id and artifact id parametrizable and run the build multiple times. Can you please file an enhancement request? That wouldn't be so difficult to implement (famous last words).

OTOH you can store all the contracts in one place and store them via e.g. topics. Then you would generate them all from a single place.

@cer
Copy link
Author

cer commented Dec 18, 2023

Yeah, we don't really support that. The only thing that comes to my mind is to make the group id and artifact id parametrizable and run the build multiple times. Can you please file an enhancement request? That wouldn't be so difficult to implement (famous last words).

IMHO

  • Request/async response is an important interaction style. eg. HTTP from API gateway to services; inter-service communication is either pub/sub (events), e.g. simple choreography-based sagas, or Request/async response, for complex orchestration-based sagas.
  • Lack of contract testing is sadly quite common.
  • Spring Cloud Contract needs to make it easy: provide "first class" support for request/async response

I think it would be better to enhance the plugin to support code generation from multiple "sources" for the contracts.

@marcingrzejszczak
Copy link
Contributor

So if we added that feature to support multiple sources for contracts, would that solve the problems with this type of communication?

@cer
Copy link
Author

cer commented Dec 21, 2023

So if we added that feature to support multiple sources for contracts, would that solve the problems with this type of communication?

Most likely

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants