spring-cloud-contract icon indicating copy to clipboard operation
spring-cloud-contract copied to clipboard

Consumer side integration test only works with @RabbitListener annotated method

Open michelvandernol opened this issue 4 years ago • 4 comments

In the project i am currently working on an application has one queue on which it receives all events, therefore we are using one receiver class (annotated with @RabbitListener) with multiple @RabbitHandler annotated methods.

It seems it is only possible to create consumer side integration tests, using the cloud contract stubrunner, when single @RabbitListener annotated methods are used on the consumer side.

Is it possible to get consumer side integration tests working based on the consumer solution in my project (@RabbitListener annotated receiver class with multiple @RabbitHandler annotated methods)?

If not is it possible to add support for this in spring-cloud-contract / stubrunner?

Example:

@Component
@RabbitListener(queues = EVENTS_QUEUE)
public class EventReceiver {

    @RabbitHandler
    void receive(Event1 event) {
        // ...
    }

    @RabbitHandler
    void receive(Event2 event) {
        // ...
    }
}

michelvandernol avatar Oct 08 '19 09:10 michelvandernol

Could you please create a small project that replicates this issue? it will be easier to debug this

marcingrzejszczak avatar Oct 21 '19 07:10 marcingrzejszczak

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

spring-projects-issues avatar Oct 28 '19 07:10 spring-projects-issues

Please do not close this issue, i am preparing a full example, which i plan to add (early) next week.

michelvandernol avatar Nov 01 '19 15:11 michelvandernol

cdc-example.zip

The example code contains two implementations, the CommandConsumer which has one @RabbitListener annotated method and the EventConsumer which contains two @RabbitHandler annotated methods. In creating this example I got the Consumer integration tests working for both consumers, however I did discover why previous attempts to get them working failed.

In our case we created one binding (ExampleConfig.java) for all events, using a wildcard in the routingKey configuration of the binding. In the production code this works perfectly, however in the spring-cloud-contract consumer side integration tests it does not, the consumer side integration testing requires exact matching routingKeys (line with routingKey.equals(binding.getRoutingKey()) in MessageListenerAccessor.java, see below) for its bindings. Checkout ExampleConfig.java for these bindings, the wildcard is currently commented out.

Is it possible to add support in case a wildcard is used in the routingKey of a binding, spring-cloud-contract consumer integration testing will also identify this binding as being correct?

MessageListenerAccessor.java

	private Set<String> collectQueuesBoundToDestination(String destination,
			String routingKey) {
		Set<String> queueNames = new HashSet<>();
		for (Binding binding : this.bindings) {
			if (destination.equals(binding.getExchange())
					&& (routingKey == null || routingKey.equals(binding.getRoutingKey()))
					&& DestinationType.QUEUE.equals(binding.getDestinationType())) {
				queueNames.add(binding.getDestination());
			}
		}
		return queueNames;
	}

michelvandernol avatar Nov 05 '19 11:11 michelvandernol