test: Simplified `ChatBackendControllerTest`
authorKai Moritz <kai@juplo.de>
Tue, 22 Aug 2023 15:33:36 +0000 (17:33 +0200)
committerKai Moritz <kai@juplo.de>
Wed, 23 Aug 2023 05:37:03 +0000 (07:37 +0200)
src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java
src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeTestBase.java [new file with mode: 0644]
src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeWithShardsTestBase.java [new file with mode: 0644]
src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/ShardedChatHomeTest.java [new file with mode: 0644]
src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHomeTest.java

index 32b1e35..9b8b09f 100644 (file)
@@ -2,8 +2,6 @@ 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.persistence.inmemory.InMemoryChatHomeService;
-import de.juplo.kafka.chat.backend.persistence.inmemory.ShardingStrategy;
 import lombok.extern.slf4j.Slf4j;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
@@ -17,10 +15,7 @@ import reactor.core.publisher.Mono;
 
 import java.time.Clock;
 import java.time.LocalDateTime;
-import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.*;
@@ -28,9 +23,6 @@ import static org.mockito.Mockito.*;
 
 @SpringBootTest(properties = {
     "spring.main.allow-bean-definition-overriding=true",
-    "chat.backend.inmemory.sharding-strategy=kafkalike",
-    "chat.backend.inmemory.num-shards=10",
-    "chat.backend.inmemory.owned-shards=6",
     })
 @AutoConfigureWebTestClient
 @Slf4j
@@ -38,11 +30,9 @@ public class ChatBackendControllerTest
 {
   @Autowired
   ChatBackendProperties properties;
-  @Autowired
-  ShardingStrategy shardingStrategy;
 
   @MockBean
-  InMemoryChatHomeService chatHomeService;
+  ChatHome chatHome;
   @MockBean
   ChatRoomService chatRoomService;
 
@@ -51,9 +41,8 @@ public class ChatBackendControllerTest
   void testUnknownChatroomExceptionForListChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
+    UUID chatroomId = UUID.randomUUID();
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -72,9 +61,8 @@ public class ChatBackendControllerTest
   void testUnknownChatroomExceptionForGetChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
+    UUID chatroomId = UUID.randomUUID();
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -92,11 +80,10 @@ public class ChatBackendControllerTest
   void testUnknownChatroomExceptionForPutMessage(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
+    UUID chatroomId = UUID.randomUUID();
     String username = "foo";
     Long messageId = 66l;
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -119,11 +106,10 @@ public class ChatBackendControllerTest
   void testUnknownChatroomExceptionForGetMessage(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
+    UUID chatroomId = UUID.randomUUID();
     String username = "foo";
     Long messageId = 66l;
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -145,9 +131,8 @@ public class ChatBackendControllerTest
   void testUnknownChatroomExceptionForListenChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
+    UUID chatroomId = UUID.randomUUID();
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new UnknownChatroomException(chatroomId));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -176,7 +161,7 @@ public class ChatBackendControllerTest
   void testMessageMutationException(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
+    UUID chatroomId = UUID.randomUUID();
     String user = "foo";
     Long messageId = 66l;
     Message.MessageKey key = Message.MessageKey.of(user, messageId);
@@ -191,7 +176,7 @@ public class ChatBackendControllerTest
         0,
         Clock.systemDefaultZone(),
         chatRoomService, 8);
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.just(chatRoom));
+    when(chatHome.getChatRoom(eq(chatroomId))).thenReturn(Mono.just(chatRoom));
     Message existingMessage = new Message(
         key,
         serialNumberExistingMessage,
@@ -232,7 +217,7 @@ public class ChatBackendControllerTest
   void testInvalidUsernameException(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForOwnedShard();
+    UUID chatroomId = UUID.randomUUID();
     String user = "Foo";
     Long messageId = 66l;
     Message.MessageKey key = Message.MessageKey.of(user, messageId);
@@ -243,7 +228,7 @@ public class ChatBackendControllerTest
         0,
         Clock.systemDefaultZone(),
         chatRoomService, 8);
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class)))
+    when(chatHome.getChatRoom(any(UUID.class)))
         .thenReturn(Mono.just(chatRoom));
     when(chatRoomService.getMessage(any(Message.MessageKey.class)))
         .thenReturn(Mono.empty());
@@ -275,7 +260,9 @@ public class ChatBackendControllerTest
   void testShardNotOwnedExceptionForGetChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForForeignShard();
+    UUID chatroomId = UUID.randomUUID();
+    int shard = 666;
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -285,7 +272,7 @@ public class ChatBackendControllerTest
         .exchange();
 
     // Then
-    assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId));
+    assertProblemDetailsForShardNotOwnedException(responseSpec, shard);
   }
 
   @Test
@@ -293,7 +280,9 @@ public class ChatBackendControllerTest
   void testShardNotOwnedExceptionForListChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForForeignShard();
+    UUID chatroomId = UUID.randomUUID();
+    int shard = 666;
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -303,18 +292,19 @@ public class ChatBackendControllerTest
         .exchange();
 
     // Then
-    assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId));
+    assertProblemDetailsForShardNotOwnedException(responseSpec, shard);
   }
 
   @Test
-  @DisplayName("Assert expected problem-details for now owned shard on PUT /put/{chatroomId}/{username}/{messageId}")
+  @DisplayName("Assert expected problem-details for not owned shard on PUT /put/{chatroomId}/{username}/{messageId}")
   void testShardNotOwnedExceptionForPutMessage(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForForeignShard();
+    UUID chatroomId = UUID.randomUUID();
     String username = "foo";
     Long messageId = 66l;
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    int shard = 666;
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -329,7 +319,7 @@ public class ChatBackendControllerTest
         .exchange();
 
     // Then
-    assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId));
+    assertProblemDetailsForShardNotOwnedException(responseSpec, shard);
   }
 
   @Test
@@ -337,10 +327,11 @@ public class ChatBackendControllerTest
   void testShardNotOwnedExceptionForGetMessage(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForForeignShard();
+    UUID chatroomId = UUID.randomUUID();
     String username = "foo";
     Long messageId = 66l;
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    int shard = 666;
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -354,7 +345,7 @@ public class ChatBackendControllerTest
         .exchange();
 
     // Then
-    assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId));
+    assertProblemDetailsForShardNotOwnedException(responseSpec, shard);
   }
 
   @Test
@@ -362,8 +353,9 @@ public class ChatBackendControllerTest
   void testShardNotOwnedExceptionForListenChatroom(@Autowired WebTestClient client)
   {
     // Given
-    UUID chatroomId = getRandomIdForForeignShard();
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    UUID chatroomId = UUID.randomUUID();
+    int shard = 666;
+    when(chatHome.getChatRoom(eq(chatroomId))).thenThrow(new ShardNotOwnedException(shard));
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -373,7 +365,7 @@ public class ChatBackendControllerTest
         .exchange();
 
     // Then
-    assertProblemDetailsForShardNotOwnedException(responseSpec, shardingStrategy.selectShard(chatroomId));
+    assertProblemDetailsForShardNotOwnedException(responseSpec, shard);
   }
 
   private void assertProblemDetailsForShardNotOwnedException(
@@ -386,40 +378,4 @@ public class ChatBackendControllerTest
         .jsonPath("$.type").isEqualTo("/problem/shard-not-owned")
         .jsonPath("$.shard").isEqualTo(shard);
   }
-
-  private UUID getRandomIdForOwnedShard()
-  {
-    Set<Integer> ownedShards = ownedShards();
-    UUID randomId;
-
-    do
-    {
-      randomId = UUID.randomUUID();
-    }
-    while (!ownedShards.contains(shardingStrategy.selectShard(randomId)));
-
-    return randomId;
-  }
-
-  private UUID getRandomIdForForeignShard()
-  {
-    Set<Integer> ownedShards = ownedShards();
-    UUID randomId;
-
-    do
-    {
-      randomId = UUID.randomUUID();
-    }
-    while (ownedShards.contains(shardingStrategy.selectShard(randomId)));
-
-    return randomId;
-  }
-
-  private Set<Integer> ownedShards()
-  {
-    return IntStream
-        .of(properties.getInmemory().getOwnedShards())
-        .mapToObj(shard -> Integer.valueOf(shard))
-        .collect(Collectors.toSet());
-  }
 }
diff --git a/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeTestBase.java b/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeTestBase.java
new file mode 100644 (file)
index 0000000..0a0b624
--- /dev/null
@@ -0,0 +1,54 @@
+package de.juplo.kafka.chat.backend.domain;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import reactor.core.publisher.Mono;
+
+import java.util.UUID;
+
+import static pl.rzrz.assertj.reactor.Assertions.assertThat;
+
+
+@ExtendWith(SpringExtension.class)
+public class ChatHomeTestBase
+{
+  @Autowired
+  ChatHome chatHome;
+
+
+  @Test
+  @DisplayName("Assert chatroom is delivered, if it exists")
+  void testGetExistingChatroom()
+  {
+    // Given
+    UUID chatRoomId = UUID.fromString("5c73531c-6fc4-426c-adcb-afc5c140a0f7");
+
+    // When
+    Mono<ChatRoom> mono = chatHome.getChatRoom(chatRoomId);
+
+    // Then
+    assertThat(mono).emitsCount(1);
+  }
+
+  @Test
+  @DisplayName("Assert UnknownChatroomException is thrown, if chatroom does not exist")
+  void testGetNonExistentChatroom()
+  {
+    // Given
+    UUID chatRoomId = UUID.fromString("7f59ec77-832e-4a17-8d22-55ef46242c17");
+
+    // When
+    Mono<ChatRoom> mono = chatHome.getChatRoom(chatRoomId);
+
+    // Then
+    assertThat(mono).sendsError(e ->
+    {
+      assertThat(e).isInstanceOf(UnknownChatroomException.class);
+      UnknownChatroomException unknownChatroomException = (UnknownChatroomException) e;
+      assertThat(unknownChatroomException.getChatroomId()).isEqualTo(chatRoomId);
+    });
+  }
+}
diff --git a/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeWithShardsTestBase.java b/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeWithShardsTestBase.java
new file mode 100644 (file)
index 0000000..a417e6f
--- /dev/null
@@ -0,0 +1,32 @@
+package de.juplo.kafka.chat.backend.domain;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import reactor.core.publisher.Mono;
+
+import java.util.UUID;
+
+import static pl.rzrz.assertj.reactor.Assertions.assertThat;
+
+
+public class ChatHomeWithShardsTestBase extends ChatHomeTestBase
+{
+  @Test
+  @DisplayName("Assert ShardNotOwnedException is thrown, if the shard for the chatroom is not owned")
+  void testGetChatroomForNotOwnedShard()
+  {
+    // Given
+    UUID chatRoomId = UUID.fromString("4e7246a6-29ae-43ea-b56f-669c3481ac19");
+
+    // When
+    Mono<ChatRoom> mono = chatHome.getChatRoom(chatRoomId);
+
+    // Then
+    assertThat(mono).sendsError(e ->
+    {
+      assertThat(e).isInstanceOf(UnknownChatroomException.class);
+      UnknownChatroomException unknownChatroomException = (UnknownChatroomException) e;
+      assertThat(unknownChatroomException.getChatroomId()).isEqualTo(chatRoomId);
+    });
+  }
+}
diff --git a/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/ShardedChatHomeTest.java b/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/ShardedChatHomeTest.java
new file mode 100644 (file)
index 0000000..ff82986
--- /dev/null
@@ -0,0 +1,73 @@
+package de.juplo.kafka.chat.backend.persistence.inmemory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.juplo.kafka.chat.backend.domain.ChatHomeWithShardsTestBase;
+import de.juplo.kafka.chat.backend.persistence.StorageStrategy;
+import de.juplo.kafka.chat.backend.persistence.storage.files.FilesStorageStrategy;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+
+import java.nio.file.Paths;
+import java.time.Clock;
+import java.util.stream.IntStream;
+
+
+public class ShardedChatHomeTest extends ChatHomeWithShardsTestBase
+{
+  @TestConfiguration
+  static class Configuration
+  {
+    @Bean
+    ShardedChatHome chatHome(
+        Integer numShards,
+        int[] ownedShards,
+        InMemoryChatHomeService chatHomeService)
+    {
+      SimpleChatHome[] chatHomes = new SimpleChatHome[numShards];
+
+      IntStream
+          .of(ownedShards)
+          .forEach(shard -> chatHomes[shard] = new SimpleChatHome(chatHomeService, shard));
+
+      ShardingStrategy strategy = new KafkaLikeShardingStrategy(numShards);
+
+      return new ShardedChatHome(chatHomes, strategy);
+    }
+
+    @Bean
+    InMemoryChatHomeService chatHomeService(
+        Integer numShards,
+        int[] ownedShards,
+        StorageStrategy storageStrategy)
+    {
+      return new InMemoryChatHomeService(
+          numShards,
+          ownedShards,
+          storageStrategy.read());
+    }
+
+    @Bean
+    public FilesStorageStrategy storageStrategy(Integer numShards)
+    {
+      return new FilesStorageStrategy(
+          Paths.get("target", "test-classes", "data", "files"),
+          Clock.systemDefaultZone(),
+          8,
+          new KafkaLikeShardingStrategy(numShards),
+          messageFlux -> new InMemoryChatRoomService(messageFlux),
+          new ObjectMapper());
+    }
+
+    @Bean
+    Integer numShards()
+    {
+      return 10;
+    }
+
+    @Bean
+    int[] ownedShards()
+    {
+      return new int[] { 2 };
+    }
+  }
+}
index e45f1a5..1e5f0d4 100644 (file)
@@ -1,59 +1,46 @@
 package de.juplo.kafka.chat.backend.persistence.inmemory;
 
-import de.juplo.kafka.chat.backend.domain.ChatRoom;
-import de.juplo.kafka.chat.backend.domain.ChatRoomService;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import reactor.core.publisher.Mono;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.juplo.kafka.chat.backend.domain.ChatHomeTestBase;
+import de.juplo.kafka.chat.backend.persistence.StorageStrategy;
+import de.juplo.kafka.chat.backend.persistence.storage.files.FilesStorageStrategy;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+
+import java.nio.file.Paths;
 import java.time.Clock;
-import java.util.UUID;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static pl.rzrz.assertj.reactor.Assertions.assertThat;
 
 
-public class SimpleChatHomeTest
+public class SimpleChatHomeTest extends ChatHomeTestBase
 {
-  @Test
-  @DisplayName("Assert chatroom is delivered, if it exists")
-  void testGetExistingChatroom()
+  @TestConfiguration
+  static class Configuration
   {
-    // Given
-    InMemoryChatHomeService chatHomeService = mock(InMemoryChatHomeService.class);
-    ChatRoom chatRoom = new ChatRoom(
-        UUID.randomUUID(),
-        "Foo",
-        0,
-        Clock.systemDefaultZone(),
-        mock(ChatRoomService.class),
-        8);
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.just(chatRoom));
-    SimpleChatHome chatHome = new SimpleChatHome(chatHomeService);
-
-    // When
-    Mono<ChatRoom> mono = chatHome.getChatRoom(chatRoom.getId());
-
-    // Then
-    assertThat(mono).emitsExactly(chatRoom);
-  }
-
-  @Test
-  @DisplayName("Assert UnknownChatroomException is thrown, if chatroom does not exist")
-  void testGetNonExistentChatroom()
-  {
-    // Given
-    InMemoryChatHomeService chatHomeService = mock(InMemoryChatHomeService.class);
-    when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
-    SimpleChatHome chatHome = new SimpleChatHome(chatHomeService);
-
-    // When
-    Mono<ChatRoom> mono = chatHome.getChatRoom(UUID.randomUUID());
-
-    // Then
-    assertThat(mono).sendsError();
+    @Bean
+    SimpleChatHome chatHome(InMemoryChatHomeService chatHomeService)
+    {
+      return new SimpleChatHome(chatHomeService);
+    }
+
+    @Bean
+    InMemoryChatHomeService chatHomeService(StorageStrategy storageStrategy)
+    {
+      return new InMemoryChatHomeService(
+          1,
+          new int[] { 0 },
+          storageStrategy.read());
+    }
+
+    @Bean
+    public FilesStorageStrategy storageStrategy()
+    {
+      return new FilesStorageStrategy(
+          Paths.get("target", "test-classes", "data", "files"),
+          Clock.systemDefaultZone(),
+          8,
+          chatRoomId -> 0,
+          messageFlux -> new InMemoryChatRoomService(messageFlux),
+          new ObjectMapper());
+    }
   }
 }