b3504d2e5f3e25945888a00d84cb77e096681608
[demos/kafka/chat] / src / test / java / de / juplo / kafka / chat / backend / api / ChatBackendControllerTest.java
1 package de.juplo.kafka.chat.backend.api;
2
3 import de.juplo.kafka.chat.backend.domain.*;
4 import lombok.extern.slf4j.Slf4j;
5 import org.junit.jupiter.api.DisplayName;
6 import org.junit.jupiter.api.Test;
7 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
9 import org.springframework.boot.test.context.SpringBootTest;
10 import org.springframework.boot.test.mock.mockito.MockBean;
11 import org.springframework.http.MediaType;
12 import org.springframework.test.web.reactive.server.WebTestClient;
13 import reactor.core.publisher.Mono;
14
15 import java.time.Clock;
16 import java.time.LocalDateTime;
17 import java.util.UUID;
18
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.Mockito.*;
21
22
23 @SpringBootTest(properties = "spring.main.allow-bean-definition-overriding=true")
24 @AutoConfigureWebTestClient
25 @Slf4j
26 public class ChatBackendControllerTest
27 {
28   @MockBean
29   ChatHomeService chatHomeService;
30   @MockBean
31   ChatRoomService chatRoomService;
32
33   @Test
34   @DisplayName("Assert expected problem-details for unknown chatroom on GET /list/{chatroomId}")
35   void testUnknownChatroomExceptionForListChatroom(@Autowired WebTestClient client)
36   {
37     // Given
38     UUID chatroomId = UUID.randomUUID();
39     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
40
41     // When
42     WebTestClient.ResponseSpec responseSpec = client
43         .get()
44         .uri("/{chatroomId}/list", chatroomId)
45         .accept(MediaType.APPLICATION_JSON)
46         .exchange();
47
48     // Then
49     assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
50   }
51
52
53   @Test
54   @DisplayName("Assert expected problem-details for unknown chatroom on GET /get/{chatroomId}")
55   void testUnknownChatroomExceptionForGetChatroom(@Autowired WebTestClient client)
56   {
57     // Given
58     UUID chatroomId = UUID.randomUUID();
59     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
60
61     // When
62     WebTestClient.ResponseSpec responseSpec = client
63         .get()
64         .uri("/{chatroomId}", chatroomId)
65         .accept(MediaType.APPLICATION_JSON)
66         .exchange();
67
68     // Then
69     assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
70   }
71
72   @Test
73   @DisplayName("Assert expected problem-details for unknown chatroom on PUT /put/{chatroomId}/{username}/{messageId}")
74   void testUnknownChatroomExceptionForPutMessage(@Autowired WebTestClient client)
75   {
76     // Given
77     UUID chatroomId = UUID.randomUUID();
78     String username = "foo";
79     Long messageId = 66l;
80     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
81
82     // When
83     WebTestClient.ResponseSpec responseSpec = client
84         .put()
85         .uri(
86             "/{chatroomId}/{username}/{messageId}",
87             chatroomId,
88             username,
89             messageId)
90         .bodyValue("bar")
91         .accept(MediaType.APPLICATION_JSON)
92         .exchange();
93
94     // Then
95     assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
96   }
97
98   @Test
99   @DisplayName("Assert expected problem-details for unknown chatroom on GET /get/{chatroomId}/{username}/{messageId}")
100   void testUnknownChatroomExceptionForGetMessage(@Autowired WebTestClient client)
101   {
102     // Given
103     UUID chatroomId = UUID.randomUUID();
104     String username = "foo";
105     Long messageId = 66l;
106     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
107
108     // When
109     WebTestClient.ResponseSpec responseSpec = client
110         .get()
111         .uri(
112             "/{chatroomId}/{username}/{messageId}",
113             chatroomId,
114             username,
115             messageId)
116         .accept(MediaType.APPLICATION_JSON)
117         .exchange();
118
119     // Then
120     assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
121   }
122
123   @Test
124   @DisplayName("Assert expected problem-details for unknown chatroom on GET /listen/{chatroomId}")
125   void testUnknownChatroomExceptionForListenChatroom(@Autowired WebTestClient client)
126   {
127     // Given
128     UUID chatroomId = UUID.randomUUID();
129     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
130
131     // When
132     WebTestClient.ResponseSpec responseSpec = client
133         .get()
134         .uri("/{chatroomId}/listen", chatroomId)
135         // .accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON) << TODO: Does not work!
136         .exchange();
137
138     // Then
139     assertProblemDetailsForUnknownChatroomException(responseSpec, chatroomId);
140   }
141
142   private void assertProblemDetailsForUnknownChatroomException(
143       WebTestClient.ResponseSpec responseSpec,
144       UUID chatroomId)
145   {
146     responseSpec
147         .expectStatus().isNotFound()
148         .expectBody()
149         .jsonPath("$.type").isEqualTo("/problem/unknown-chatroom")
150         .jsonPath("$.chatroomId").isEqualTo(chatroomId.toString());
151   }
152
153   @Test
154   @DisplayName("Assert expected problem-details for message mutation on PUT /put/{chatroomId}/{username}/{messageId}")
155   void testMessageMutationException(@Autowired WebTestClient client) throws Exception
156   {
157     // Given
158     UUID chatroomId = UUID.randomUUID();
159     String user = "foo";
160     Long messageId = 66l;
161     Message.MessageKey key = Message.MessageKey.of(user, messageId);
162     Long serialNumberExistingMessage = 0l;
163     String timeExistingMessageAsString = "2023-01-09T20:44:57.389665447";
164     LocalDateTime timeExistingMessage = LocalDateTime.parse(timeExistingMessageAsString);
165     String textExistingMessage = "Existing";
166     String textMutatedMessage = "Mutated!";
167     ChatRoom chatRoom = new ChatRoom(
168         chatroomId,
169         "Test-ChatRoom",
170         0,
171         Clock.systemDefaultZone(),
172         chatRoomService, 8);
173     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.just(chatRoom));
174     Message existingMessage = new Message(
175         key,
176         serialNumberExistingMessage,
177         timeExistingMessage,
178         textExistingMessage);
179     when(chatRoomService.getMessage(any(Message.MessageKey.class)))
180         .thenReturn(Mono.just(existingMessage));
181     // Needed for readable error-reports, in case of a bug that leads to according unwanted call
182     when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class)))
183         .thenReturn(mock(Message.class));
184
185     // When
186     client
187         .put()
188         .uri(
189             "/{chatroomId}/{username}/{messageId}",
190             chatroomId,
191             user,
192             messageId)
193         .bodyValue(textMutatedMessage)
194         .accept(MediaType.APPLICATION_JSON)
195         .exchange()
196         // Then
197         .expectStatus().is4xxClientError()
198         .expectBody()
199         .jsonPath("$.type").isEqualTo("/problem/message-mutation")
200         .jsonPath("$.existingMessage.id").isEqualTo(messageId)
201         .jsonPath("$.existingMessage.serial").isEqualTo(serialNumberExistingMessage)
202         .jsonPath("$.existingMessage.time").isEqualTo(timeExistingMessageAsString)
203         .jsonPath("$.existingMessage.user").isEqualTo(user)
204         .jsonPath("$.existingMessage.text").isEqualTo(textExistingMessage)
205         .jsonPath("$.mutatedText").isEqualTo(textMutatedMessage);
206     verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class));
207   }
208
209   @Test
210   @DisplayName("Assert expected problem-details for invalid username on PUT /put/{chatroomId}/{username}/{messageId}")
211   void testInvalidUsernameException(@Autowired WebTestClient client) throws Exception
212   {
213     // Given
214     UUID chatroomId = UUID.randomUUID();
215     String user = "Foo";
216     Long messageId = 66l;
217     Message.MessageKey key = Message.MessageKey.of(user, messageId);
218     String textMessage = "Hallo Welt";
219     ChatRoom chatRoom = new ChatRoom(
220         chatroomId,
221         "Test-ChatRoom",
222         0,
223         Clock.systemDefaultZone(),
224         chatRoomService, 8);
225     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class)))
226         .thenReturn(Mono.just(chatRoom));
227     when(chatRoomService.getMessage(any(Message.MessageKey.class)))
228         .thenReturn(Mono.empty());
229     // Needed for readable error-reports, in case of a bug that leads to according unwanted call
230     when(chatRoomService.persistMessage(any(Message.MessageKey.class), any(LocalDateTime.class), any(String.class)))
231         .thenReturn(mock(Message.class));
232
233     // When
234     client
235         .put()
236         .uri(
237             "/{chatroomId}/{username}/{messageId}",
238             chatroomId,
239             user,
240             messageId)
241         .bodyValue(textMessage)
242         .accept(MediaType.APPLICATION_JSON)
243         .exchange()
244         // Then
245         .expectStatus().is4xxClientError()
246         .expectBody()
247         .jsonPath("$.type").isEqualTo("/problem/invalid-username")
248         .jsonPath("$.username").isEqualTo(user);
249     verify(chatRoomService, never()).persistMessage(eq(key), any(LocalDateTime.class), any(String.class));
250   }
251 }