All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.ght1pc9kc.testy.beat.messaging.MockedReceiver Maven / Gradle / Ivy

The newest version!
package fr.ght1pc9kc.testy.beat.messaging;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Delivery;
import fr.ght1pc9kc.testy.beat.extensions.WithRabbitMock;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * Receiver injectable by the extension {@link WithRabbitMock}.
 * 

* Usage: *

 * {@literal @}Test
 * void my_test(MockedReceiver mockedReceiver, Channel channel) {
 *     final Flux<Delivery> receivedMessages = mockedReceiver.consumeOne().on("my-queue").start();
 *
 *     // Send message
 *     final String message = "test-message";
 *     channel.basicPublish("", "my-queue", null, message.getBytes());
 *
 *     // Obtain the messages sent on the queue
 *     final String actualMessage = receivedMessages.map(d -> new String(d.getBody()))
 *             .single()
 *             .block();
 *     Assertions.assertThat(actualMessage).isEqualTo(message);
 * }
 * 
*

* The number of consumed messages can be parameterized. * The Flux returned by {@link MockedConsumerBuilder#start()} only completes when the expected number of messages is reached. *

 * {@literal @}Test
 * void my_test(MockedReceiver mockedReceiver, Channel channel) throws IOException {
 *     final String[] messages = {"test-message-1", "test-message-2"};
 *     final Flux<Delivery> receivedMessages = mockedReceiver.consume(2).on("my-queue").start();
 *
 *     // Send message
 *     channel.basicPublish("", "my-queue", null, messages[0].getBytes());
 *     channel.basicPublish("", "my-queue", null, messages[1].getBytes());
 *
 *     // Obtain the messages sent on the queue
 *     final List<String> actualMessages = receivedMessages.map(d -> new String(d.getBody()))
 *             .collectList()
 *             .block();
 *     Assertions.assertThat(actualMessages).containsExactly(messages);
 * }
 * 
*

* Responses of the receiver can be defined with model {@link AmqpMessage}. * If there are more responses than requests, the last response is replied indefinitely. *

 * {@literal @}Test
 * void my_test(MockedReceiver mockedReceiver, Channel channel) throws IOException {
 *     final String expectedRequest = "test-request";
 *     final String expectedResponse = "test-response";
 *
 *     final Flux<Delivery> receivedMessages = mockedReceiver.consumeOne().on("my-queue")
 *             .thenRespond(AmqpMessage.of(expectedResponse.getBytes()))
 *             .start();
 *
 *     final RpcClient rpcClient = new RpcClient(Mono.just(channel), "my-exchange", "", () -> UUID.randomUUID().toString());
 *
 *     // Send RPC request
 *     final Delivery response = rpcClient.rpc(Mono.just(new RpcClient.RpcRequest(expectedRequest.getBytes())))
 *             .block();
 *     Assertions.assertThat(response).isNotNull();
 *     Assertions.assertThat(response.getBody()).isNotEmpty();
 *     Assertions.assertThat(new String(response.getBody())).isEqualTo(expectedResponse);
 *
 *     // Obtain the messages sent on the queue
 *     final String actualRequest = receivedMessages.map(d -> new String(d.getBody()))
 *             .single()
 *             .block();
 *     Assertions.assertThat(actualRequest).isEqualTo(expectedRequest);
 * }
 * 
*/ public final class MockedReceiver { private final Channel channel; /** * Constructor. * * @param channel Channel used to consume the messages. */ public MockedReceiver(Channel channel) { this.channel = channel; } /** * Define the number of requests to consume on the queue. * * @param nbRequests Number of requests to consume on the queue (min. 1). * @return {@link FixedRequestsConsumerBuilder}. */ public FixedRequestsConsumerBuilder consume(int nbRequests) { if (nbRequests < 1) { throw new IllegalArgumentException("Expect at least 1 request to be consumed"); } return new FixedRequestsConsumerBuilder(channel, nbRequests); } /** * Consume on request on a queue. * * @return {@link FixedRequestsConsumerBuilder}. */ public FixedRequestsConsumerBuilder consumeOne() { return consume(1); } /** * Intermediate builder for mocked consumer. */ @AllArgsConstructor(access = AccessLevel.PRIVATE) public static final class FixedRequestsConsumerBuilder { private final Channel channel; private final int nbRequests; /** * Define the queue on which the messages are consumed. * * @param queue The queue on which the messages are consumed. * @return {@link MockedConsumerBuilder}. */ public MockedConsumerBuilder on(String queue) { return new MockedConsumerBuilder(channel, nbRequests, queue); } } /** * Intermediate builder for mocked consumer. */ public static final class MockedConsumerBuilder { private final Channel channel; private final int nbRequests; private final String queue; private final Queue responses; private MockedConsumerBuilder(Channel channel, int nbRequests, String queue) { this.channel = channel; this.nbRequests = nbRequests; this.queue = queue; this.responses = new ArrayBlockingQueue<>(nbRequests); } /** * Define the next respond for a request. * * @param response Next response to reply for a request. * @return Builder instance. */ public MockedConsumerBuilder thenRespond(AmqpMessage response) { this.responses.offer(response); return this; } /** * Start consuming the given number of requests on the given queue. * * @return Flux of received requests. This flux is completed when the number of requests is reached. */ public Flux start() { final MockedConsumer consumer = new MockedConsumer(channel, nbRequests, responses); try { channel.basicConsume(queue, true, consumer); return consumer.getReceivedRequests(); } catch (IOException e) { throw new IllegalStateException(e); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy