diff --git a/src/test/java/de/dev089/eventproducer/config/RabbitConfigurationTest.java b/src/test/java/de/dev089/eventproducer/config/RabbitConfigurationTest.java new file mode 100644 index 0000000..0af65d0 --- /dev/null +++ b/src/test/java/de/dev089/eventproducer/config/RabbitConfigurationTest.java @@ -0,0 +1,37 @@ +package de.dev089.eventproducer.config; + +import org.junit.jupiter.api.Test; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +class RabbitConfigurationTest { + + @Test + void beans_areConfiguredFromProperties() { + RabbitConfiguration config = new RabbitConfiguration(); + ReflectionTestUtils.setField(config, "producerExchange", "exchange.x"); + ReflectionTestUtils.setField(config, "queueName", "queue.q"); + ReflectionTestUtils.setField(config, "routingKey", "route.r"); + + TopicExchange exchange = config.topicExchange(); + Queue queue = config.producerQueue(); + Binding binding = config.queueBinding(queue, exchange); + MessageConverter converter = config.jacksonConverter(); + RabbitTemplate template = config.rabbitTemplate(mock(ConnectionFactory.class), converter); + + assertThat(exchange.getName()).isEqualTo("exchange.x"); + assertThat(exchange.isDurable()).isTrue(); + assertThat(queue.getName()).isEqualTo("queue.q"); + assertThat(binding.getRoutingKey()).isEqualTo("route.r"); + assertThat(template.getExchange()).isEqualTo("exchange.x"); + assertThat(template.getMessageConverter()).isSameAs(converter); + } +} diff --git a/src/test/java/de/dev089/eventproducer/producer/HealthRequestProducerTest.java b/src/test/java/de/dev089/eventproducer/producer/HealthRequestProducerTest.java new file mode 100644 index 0000000..e341ff0 --- /dev/null +++ b/src/test/java/de/dev089/eventproducer/producer/HealthRequestProducerTest.java @@ -0,0 +1,30 @@ +package de.dev089.eventproducer.producer; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +import static org.mockito.Mockito.verify; + +class HealthRequestProducerTest { + + @Test + void publish_usesProvidedRoutingKey() { + RabbitTemplate rabbitTemplate = Mockito.mock(RabbitTemplate.class); + HealthRequestProducer producer = new HealthRequestProducer(rabbitTemplate, "default.route"); + + producer.publish("custom.route", "payload"); + + verify(rabbitTemplate).convertAndSend("custom.route", "payload"); + } + + @Test + void publishToDefaultQueue_usesDefaultRoutingKey() { + RabbitTemplate rabbitTemplate = Mockito.mock(RabbitTemplate.class); + HealthRequestProducer producer = new HealthRequestProducer(rabbitTemplate, "default.route"); + + producer.publishToDefaultQueue("payload"); + + verify(rabbitTemplate).convertAndSend("default.route", "payload"); + } +} diff --git a/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerIT.java b/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerIT.java new file mode 100644 index 0000000..abe48eb --- /dev/null +++ b/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerIT.java @@ -0,0 +1,49 @@ +package de.dev089.eventproducer.web; + +import de.dev089.eventproducer.producer.HealthRequestProducer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(properties = { + "RABBITMQ_HOST=localhost", + "RABBITMQ_PORT=5672", + "RABBITMQ_USERNAME=guest", + "RABBITMQ_PASSWORD=guest" +}) +@AutoConfigureMockMvc +class RequestProducerControllerIT { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private HealthRequestProducer healthRequestProducer; + + @Test + void postPopulate_acceptsValidRequest() throws Exception { + mockMvc.perform(post("/api/events/populate") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"message\":\"hello\"}")) + .andExpect(status().isAccepted()); + + verify(healthRequestProducer).publishToDefaultQueue(any()); + } + + @Test + void postPopulate_rejectsInvalidRequest() throws Exception { + mockMvc.perform(post("/api/events/populate") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"message\":\"\"}")) + .andExpect(status().isBadRequest()); + } +} diff --git a/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerTest.java b/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerTest.java new file mode 100644 index 0000000..30ffc83 --- /dev/null +++ b/src/test/java/de/dev089/eventproducer/web/RequestProducerControllerTest.java @@ -0,0 +1,32 @@ +package de.dev089.eventproducer.web; + +import de.dev089.eventproducer.producer.HealthRequestProducer; +import de.dev089.eventproducer.web.dto.MessageRequest; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.time.Instant; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; + +class RequestProducerControllerTest { + + @Test + void publishMessage_wrapsMessageAndTimestamp() { + HealthRequestProducer producer = Mockito.mock(HealthRequestProducer.class); + RequestProducerController controller = new RequestProducerController(producer); + + controller.publishMessage(new MessageRequest("hello")); + + ArgumentCaptor> captor = ArgumentCaptor.forClass(Map.class); + verify(producer).publishToDefaultQueue(captor.capture()); + + Map envelope = captor.getValue(); + assertThat(envelope.get("message")).isEqualTo("hello"); + assertThat(envelope.get("sentAt")).isInstanceOf(String.class); + assertThat(Instant.parse((String) envelope.get("sentAt"))).isNotNull(); + } +} diff --git a/src/test/java/de/dev089/eventproducer/web/dto/MessageRequestValidationTest.java b/src/test/java/de/dev089/eventproducer/web/dto/MessageRequestValidationTest.java new file mode 100644 index 0000000..85b33ff --- /dev/null +++ b/src/test/java/de/dev089/eventproducer/web/dto/MessageRequestValidationTest.java @@ -0,0 +1,22 @@ +package de.dev089.eventproducer.web.dto; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class MessageRequestValidationTest { + + private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); + + @Test + void message_mustNotBeBlank() { + Set> violations = validator.validate(new MessageRequest("")); + + assertThat(violations).isNotEmpty(); + } +}