1 package de.juplo.kafka.chat.backend.api;
3 import de.juplo.kafka.chat.backend.domain.*;
4 import de.juplo.kafka.chat.backend.persistence.inmemory.InMemoryChatHomeService;
5 import lombok.extern.slf4j.Slf4j;
6 import org.junit.jupiter.api.DisplayName;
7 import org.junit.jupiter.api.Test;
8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
10 import org.springframework.boot.test.context.SpringBootTest;
11 import org.springframework.boot.test.mock.mockito.MockBean;
12 import org.springframework.http.MediaType;
13 import org.springframework.test.web.reactive.server.WebTestClient;
14 import reactor.core.publisher.Mono;
16 import java.time.Clock;
17 import java.time.LocalDateTime;
18 import java.util.UUID;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.Mockito.*;
24 @SpringBootTest(properties = {
25 "spring.main.allow-bean-definition-overriding=true",
26 "chat.backend.inmemory.sharding-strategy=none" })
27 @AutoConfigureWebTestClient
29 public class ChatBackendControllerTest
32 InMemoryChatHomeService chatHomeService;
34 ChatRoomService chatRoomService;
37 @DisplayName("Assert expected problem-details for unknown chatroom on GET /list/{chatroomId}")
38 void testUnknownChatroomExceptionForListChatroom(@Autowired WebTestClient client)
41 UUID chatroomId = UUID.randomUUID();
42 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
45 WebTestClient.ResponseSpec responseSpec = client
47 .uri("/{chatroomId}/list", chatroomId)
48 .accept(MediaType.APPLICATION_JSON)
52 assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
57 @DisplayName("Assert expected problem-details for unknown chatroom on GET /get/{chatroomId}")
58 void testUnknownChatroomExceptionForGetChatroom(@Autowired WebTestClient client)
61 UUID chatroomId = UUID.randomUUID();
62 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
65 WebTestClient.ResponseSpec responseSpec = client
67 .uri("/{chatroomId}", chatroomId)
68 .accept(MediaType.APPLICATION_JSON)
72 assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
76 @DisplayName("Assert expected problem-details for unknown chatroom on PUT /put/{chatroomId}/{username}/{messageId}")
77 void testUnknownChatroomExceptionForPutMessage(@Autowired WebTestClient client)
80 UUID chatroomId = UUID.randomUUID();
81 String username = "foo";
83 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
86 WebTestClient.ResponseSpec responseSpec = client
89 "/{chatroomId}/{username}/{messageId}",
94 .accept(MediaType.APPLICATION_JSON)
98 assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
102 @DisplayName("Assert expected problem-details for unknown chatroom on GET /get/{chatroomId}/{username}/{messageId}")
103 void testUnknownChatroomExceptionForGetMessage(@Autowired WebTestClient client)
106 UUID chatroomId = UUID.randomUUID();
107 String username = "foo";
108 Long messageId = 66l;
109 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
112 WebTestClient.ResponseSpec responseSpec = client
115 "/{chatroomId}/{username}/{messageId}",
119 .accept(MediaType.APPLICATION_JSON)
123 assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
127 @DisplayName("Assert expected problem-details for unknown chatroom on GET /listen/{chatroomId}")
128 void testUnknownChatroomExceptionForListenChatroom(@Autowired WebTestClient client)
131 UUID chatroomId = UUID.randomUUID();
132 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
135 WebTestClient.ResponseSpec responseSpec = client
137 .uri("/{chatroomId}/listen", chatroomId)
138 // .accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON) << TODO: Does not work!
142 assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
145 private void assertProblemDetailsForUnknownChatroomException(
146 WebTestClient.ResponseSpec responseSpec,
150 .expectStatus().isNotFound()
152 .jsonPath("$.type").isEqualTo("/problem/unknown-chatroom")
153 .jsonPath("$.chatroomId").isEqualTo(chatroomId.toString());
157 @DisplayName("Assert expected problem-details for message mutation on PUT /put/{chatroomId}/{username}/{messageId}")
158 void testMessageMutationException(@Autowired WebTestClient client) throws Exception
161 UUID chatroomId = UUID.randomUUID();
163 Long messageId = 66l;
164 Message.MessageKey key = Message.MessageKey.of(user, messageId);
165 Long serialNumberExistingMessage = 0l;
166 String timeExistingMessageAsString = "2023-01-09T20:44:57.389665447";
167 LocalDateTime timeExistingMessage = LocalDateTime.parse(timeExistingMessageAsString);
168 String textExistingMessage = "Existing";
169 String textMutatedMessage = "Mutated!";
170 ChatRoom chatRoom = new ChatRoom(
173 Clock.systemDefaultZone(),
175 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.just(chatRoom));
176 Message existingMessage = new Message(
178 serialNumberExistingMessage,
180 textExistingMessage);
181 when(chatRoomService.getMessage(any(Message.MessageKey.class)))
182 .thenReturn(Mono.just(existingMessage));
183 // Needed for readable error-reports, in case of a bug that leads to according unwanted call
184 when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class)))
185 .thenReturn(mock(Message.class));
191 "/{chatroomId}/{username}/{messageId}",
195 .bodyValue(textMutatedMessage)
196 .accept(MediaType.APPLICATION_JSON)
199 .expectStatus().is4xxClientError()
201 .jsonPath("$.type").isEqualTo("/problem/message-mutation")
202 .jsonPath("$.existingMessage.id").isEqualTo(messageId)
203 .jsonPath("$.existingMessage.serial").isEqualTo(serialNumberExistingMessage)
204 .jsonPath("$.existingMessage.time").isEqualTo(timeExistingMessageAsString)
205 .jsonPath("$.existingMessage.user").isEqualTo(user)
206 .jsonPath("$.existingMessage.text").isEqualTo(textExistingMessage)
207 .jsonPath("$.mutatedText").isEqualTo(textMutatedMessage);
208 verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class));
212 @DisplayName("Assert expected problem-details for invalid username on PUT /put/{chatroomId}/{username}/{messageId}")
213 void testInvalidUsernameException(@Autowired WebTestClient client) throws Exception
216 UUID chatroomId = UUID.randomUUID();
218 Long messageId = 66l;
219 Message.MessageKey key = Message.MessageKey.of(user, messageId);
220 String textMessage = "Hallo Welt";
221 ChatRoom chatRoom = new ChatRoom(
224 Clock.systemDefaultZone(),
226 when(chatHomeService.getChatRoom(anyInt(), any(UUID.class)))
227 .thenReturn(Mono.just(chatRoom));
228 when(chatRoomService.getMessage(any(Message.MessageKey.class)))
229 .thenReturn(Mono.empty());
230 // Needed for readable error-reports, in case of a bug that leads to according unwanted call
231 when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class)))
232 .thenReturn(mock(Message.class));
238 "/{chatroomId}/{username}/{messageId}",
242 .bodyValue(textMessage)
243 .accept(MediaType.APPLICATION_JSON)
246 .expectStatus().is4xxClientError()
248 .jsonPath("$.type").isEqualTo("/problem/invalid-username")
249 .jsonPath("$.username").isEqualTo(user);
250 verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class));