package bo.gotthardt.queue.rabbitmq; import com.codahale.metrics.MetricRegistry; import com.fasterxml.jackson.core.JsonProcessingException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Envelope; import io.dropwizard.jackson.Jackson; import lombok.Getter; import lombok.NoArgsConstructor; import org.junit.Before; import org.junit.Test; import java.io.IOException; import static bo.gotthardt.test.assertj.DropwizardAssertions.assertThat; import static org.mockito.Mockito.*; /** * Tests for {@link bo.gotthardt.queue.rabbitmq.FunctionConsumer}. */ public class FunctionConsumerTest { private Channel channel = mock(Channel.class); private Envelope envelope = mock(Envelope.class); private MetricRegistry metrics = new MetricRegistry(); private byte[] message; @Before public void setup() throws JsonProcessingException { when(envelope.getDeliveryTag()).thenReturn(1L); message = Jackson.newObjectMapper().writeValueAsBytes(new TestMsg("test", 2)); } @Test public void shouldMapMessageToType() throws IOException { FunctionConsumer<TestMsg> consumer = new FunctionConsumer<>(channel, msg -> { assertThat(msg.getName()).isEqualTo("test"); assertThat(msg.getCount()).isEqualTo(2); return null; }, TestMsg.class, "name", metrics); consumer.handleDelivery(null, envelope, null, message); } @Test public void shouldAcknowledgeMessage() throws IOException { FunctionConsumer<TestMsg> consumer = new FunctionConsumer<>(channel, msg -> null, TestMsg.class, "name", metrics); consumer.handleDelivery(null, envelope, null, message); verify(channel).basicAck(1L, false); } @Test public void shouldRejectMessageOnException() throws IOException { FunctionConsumer<TestMsg> consumer = new FunctionConsumer<>(channel, msg -> { throw new RuntimeException("Message processing failed on purpose."); }, TestMsg.class, "name", metrics); consumer.handleDelivery(null, envelope, null, message); verify(channel).basicNack(1L, false, true); } @Test public void shouldRecordConsumeSuccessMetrics() throws IOException { FunctionConsumer<TestMsg> consumer = new FunctionConsumer<>(channel, msg -> null, TestMsg.class, "name", metrics); consumer.handleDelivery(null, envelope, null, message); assertThat(metrics.meter("queue.TestMsg.name.consume.success.count").getCount()).isEqualTo(1); assertThat(metrics.timer("queue.TestMsg.name.consume.success.duration").getCount()).isEqualTo(1); } @Test public void shouldRecordConsumeFailureMetrics() throws IOException { FunctionConsumer<TestMsg> consumer = new FunctionConsumer<>(channel, msg -> { throw new RuntimeException("Message processing failed on purpose."); }, TestMsg.class, "name", metrics); consumer.handleDelivery(null, envelope, null, message); assertThat(metrics.meter("queue.TestMsg.name.consume.failure.count").getCount()).isEqualTo(1); assertThat(metrics.timer("queue.TestMsg.name.consume.failure.duration").getCount()).isEqualTo(1); } @NoArgsConstructor private static class TestMsg { @Getter private String name; @Getter private int count; private TestMsg(String name, int count) { this.name = name; this.count = count; } } }