X-Git-Url: http://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Fkafka%2Fchat%2Fbackend%2Fapi%2FChatBackendControllerTest.java;h=f831dbafff1d9ca9514d5ff6b25433ebc8db7b58;hb=df207aa9a8cd349fd43785270d250a7f55593801;hp=5e3c9283b538ccb25d943ca417716d0b0993af7f;hpb=212c5eb7912fd15768ddab961d104b27acc620a0;p=demos%2Fkafka%2Fchat diff --git a/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java b/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java index 5e3c9283..f831dbaf 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java +++ b/src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java @@ -1,6 +1,9 @@ package de.juplo.kafka.chat.backend.api; +import de.juplo.kafka.chat.backend.ChatBackendProperties; import de.juplo.kafka.chat.backend.domain.*; +import de.juplo.kafka.chat.backend.domain.exceptions.ShardNotOwnedException; +import de.juplo.kafka.chat.backend.domain.exceptions.UnknownChatroomException; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -12,21 +15,28 @@ import org.springframework.http.MediaType; import org.springframework.test.web.reactive.server.WebTestClient; import reactor.core.publisher.Mono; +import java.time.Clock; import java.time.LocalDateTime; import java.util.UUID; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; -@SpringBootTest(properties = "spring.main.allow-bean-definition-overriding=true") +@SpringBootTest(properties = { + "spring.main.allow-bean-definition-overriding=true", + }) @AutoConfigureWebTestClient @Slf4j public class ChatBackendControllerTest { + @Autowired + ChatBackendProperties properties; + @MockBean ChatHome chatHome; + @MockBean + ChatRoomService chatRoomService; @Test @DisplayName("Assert expected problem-details for unknown chatroom on GET /list/{chatroomId}") @@ -34,13 +44,12 @@ public class ChatBackendControllerTest { // Given UUID chatroomId = UUID.randomUUID(); - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.error(() -> new UnknownChatroomException(chatroomId))); + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId)); // When WebTestClient.ResponseSpec responseSpec = client .get() - .uri("/list/{chatroomId}", chatroomId) + .uri("/{chatroomId}/list", chatroomId) .accept(MediaType.APPLICATION_JSON) .exchange(); @@ -55,13 +64,12 @@ public class ChatBackendControllerTest { // Given UUID chatroomId = UUID.randomUUID(); - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.error(() -> new UnknownChatroomException(chatroomId))); + when(chatHome.getChatRoomInfo(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId)); // When WebTestClient.ResponseSpec responseSpec = client .get() - .uri("/get/{chatroomId}", chatroomId) + .uri("/{chatroomId}", chatroomId) .accept(MediaType.APPLICATION_JSON) .exchange(); @@ -77,14 +85,13 @@ public class ChatBackendControllerTest UUID chatroomId = UUID.randomUUID(); String username = "foo"; Long messageId = 66l; - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.error(() -> new UnknownChatroomException(chatroomId))); + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId)); // When WebTestClient.ResponseSpec responseSpec = client .put() .uri( - "/put/{chatroomId}/{username}/{messageId}", + "/{chatroomId}/{username}/{messageId}", chatroomId, username, messageId) @@ -104,14 +111,13 @@ public class ChatBackendControllerTest UUID chatroomId = UUID.randomUUID(); String username = "foo"; Long messageId = 66l; - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.error(() -> new UnknownChatroomException(chatroomId))); + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId)); // When WebTestClient.ResponseSpec responseSpec = client .get() .uri( - "/get/{chatroomId}/{username}/{messageId}", + "/{chatroomId}/{username}/{messageId}", chatroomId, username, messageId) @@ -128,13 +134,12 @@ public class ChatBackendControllerTest { // Given UUID chatroomId = UUID.randomUUID(); - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.error(() -> new UnknownChatroomException(chatroomId))); + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId)); // When WebTestClient.ResponseSpec responseSpec = client .get() - .uri("/listen/{chatroomId}", chatroomId) + .uri("/{chatroomId}/listen", chatroomId) // .accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON) << TODO: Does not work! .exchange(); @@ -155,37 +160,220 @@ public class ChatBackendControllerTest @Test @DisplayName("Assert expected problem-details for message mutation on PUT /put/{chatroomId}/{username}/{messageId}") - void testMessageMutationException(@Autowired WebTestClient client) throws Exception + void testMessageMutationException(@Autowired WebTestClient client) { // Given UUID chatroomId = UUID.randomUUID(); - String username = "foo"; + String user = "foo"; Long messageId = 66l; - ChatRoom chatRoom = mock(ChatRoom.class); - when(chatHome.getChatRoom(any(UUID.class))) - .thenReturn(Mono.just(chatRoom)); - Message.MessageKey key = Message.MessageKey.of("foo", 1l); - LocalDateTime timestamp = LocalDateTime.now(); - Message existing = new Message(key, 0l, timestamp, "Existing"); - when(chatRoom.addMessage(any(Long.class), any(String.class), any(String.class))) - .thenReturn(Mono.error(() -> new MessageMutationException(existing, "Mutated!"))); + Message.MessageKey key = Message.MessageKey.of(user, messageId); + Long serialNumberExistingMessage = 0l; + String timeExistingMessageAsString = "2023-01-09T20:44:57.389665447"; + LocalDateTime timeExistingMessage = LocalDateTime.parse(timeExistingMessageAsString); + String textExistingMessage = "Existing"; + String textMutatedMessage = "Mutated!"; + ChatRoomData chatRoomData = new ChatRoomData( + Clock.systemDefaultZone(), + chatRoomService, + 8); + when(chatHome.getChatRoomData(eq(chatroomId))).thenReturn(Mono.just(chatRoomData)); + Message existingMessage = new Message( + key, + serialNumberExistingMessage, + timeExistingMessage, + textExistingMessage); + when(chatRoomService.getMessage(any(Message.MessageKey.class))) + .thenReturn(Mono.just(existingMessage)); + // Needed for readable error-reports, in case of a bug that leads to according unwanted call + when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class))) + .thenReturn(Mono.just(mock(Message.class))); // When client .put() .uri( - "/put/{chatroomId}/{username}/{messageId}", + "/{chatroomId}/{username}/{messageId}", chatroomId, - username, + user, messageId) - .bodyValue("bar") + .bodyValue(textMutatedMessage) .accept(MediaType.APPLICATION_JSON) .exchange() // Then .expectStatus().is4xxClientError() .expectBody() .jsonPath("$.type").isEqualTo("/problem/message-mutation") - .jsonPath("$.existingMessage.text").isEqualTo("Existing") - .jsonPath("$.mutatedText").isEqualTo("Mutated!"); + .jsonPath("$.existingMessage.id").isEqualTo(messageId) + .jsonPath("$.existingMessage.serial").isEqualTo(serialNumberExistingMessage) + .jsonPath("$.existingMessage.time").isEqualTo(timeExistingMessageAsString) + .jsonPath("$.existingMessage.user").isEqualTo(user) + .jsonPath("$.existingMessage.text").isEqualTo(textExistingMessage) + .jsonPath("$.mutatedText").isEqualTo(textMutatedMessage); + verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class)); + } + + @Test + @DisplayName("Assert expected problem-details for invalid username on PUT /put/{chatroomId}/{username}/{messageId}") + void testInvalidUsernameException(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + String user = "Foo"; + Long messageId = 66l; + Message.MessageKey key = Message.MessageKey.of(user, messageId); + String textMessage = "Hallo Welt"; + ChatRoomData chatRoomData = new ChatRoomData( + Clock.systemDefaultZone(), + chatRoomService, + 8); + when(chatHome.getChatRoomData(any(UUID.class))) + .thenReturn(Mono.just(chatRoomData)); + when(chatRoomService.getMessage(any(Message.MessageKey.class))) + .thenReturn(Mono.empty()); + // Needed for readable error-reports, in case of a bug that leads to according unwanted call + when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class))) + .thenReturn(Mono.just(mock(Message.class))); + + // When + client + .put() + .uri( + "/{chatroomId}/{username}/{messageId}", + chatroomId, + user, + messageId) + .bodyValue(textMessage) + .accept(MediaType.APPLICATION_JSON) + .exchange() + // Then + .expectStatus().is4xxClientError() + .expectBody() + .jsonPath("$.type").isEqualTo("/problem/invalid-username") + .jsonPath("$.username").isEqualTo(user); + verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class)); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /{chatroomId}") + void testShardNotOwnedExceptionForGetChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + int shard = 666; + when(chatHome.getChatRoomInfo(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard)); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}", chatroomId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shard); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /list/{chatroomId}") + void testShardNotOwnedExceptionForListChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + int shard = 666; + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard)); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}/list", chatroomId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shard); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on PUT /put/{chatroomId}/{username}/{messageId}") + void testShardNotOwnedExceptionForPutMessage(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + String username = "foo"; + Long messageId = 66l; + int shard = 666; + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard)); + + // When + WebTestClient.ResponseSpec responseSpec = client + .put() + .uri( + "/{chatroomId}/{username}/{messageId}", + chatroomId, + username, + messageId) + .bodyValue("bar") + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shard); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /get/{chatroomId}/{username}/{messageId}") + void testShardNotOwnedExceptionForGetMessage(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + String username = "foo"; + Long messageId = 66l; + int shard = 666; + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard)); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri( + "/{chatroomId}/{username}/{messageId}", + chatroomId, + username, + messageId) + .accept(MediaType.APPLICATION_JSON) + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shard); + } + + @Test + @DisplayName("Assert expected problem-details for not owned shard on GET /listen/{chatroomId}") + void testShardNotOwnedExceptionForListenChatroom(@Autowired WebTestClient client) + { + // Given + UUID chatroomId = UUID.randomUUID(); + int shard = 666; + when(chatHome.getChatRoomData(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard)); + + // When + WebTestClient.ResponseSpec responseSpec = client + .get() + .uri("/{chatroomId}/listen", chatroomId) + // .accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON) << TODO: Does not work! + .exchange(); + + // Then + assertProblemDetailsForShardNotOwnedException(responseSpec, shard); + } + + private void assertProblemDetailsForShardNotOwnedException( + WebTestClient.ResponseSpec responseSpec, + int shard) + { + responseSpec + .expectStatus().isNotFound() + .expectBody() + .jsonPath("$.type").isEqualTo("/problem/shard-not-owned") + .jsonPath("$.shard").isEqualTo(shard); } }