From bb1f9a4b980e35790cef4892063ab6186f2b7084 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Tue, 22 Aug 2023 17:33:36 +0200 Subject: [PATCH] test: Simplified `ChatBackendControllerTest` --- .../api/ChatBackendControllerTest.java | 116 ++++++------------ .../chat/backend/domain/ChatHomeTestBase.java | 54 ++++++++ .../domain/ChatHomeWithShardsTestBase.java | 32 +++++ .../inmemory/ShardedChatHomeTest.java | 73 +++++++++++ .../inmemory/SimpleChatHomeTest.java | 87 ++++++------- 5 files changed, 232 insertions(+), 130 deletions(-) create mode 100644 src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeTestBase.java create mode 100644 src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeWithShardsTestBase.java create mode 100644 src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/ShardedChatHomeTest.java 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 32b1e357..9b8b09f8 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 @@ -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 ownedShards = ownedShards(); - UUID randomId; - - do - { - randomId = UUID.randomUUID(); - } - while (!ownedShards.contains(shardingStrategy.selectShard(randomId))); - - return randomId; - } - - private UUID getRandomIdForForeignShard() - { - Set ownedShards = ownedShards(); - UUID randomId; - - do - { - randomId = UUID.randomUUID(); - } - while (ownedShards.contains(shardingStrategy.selectShard(randomId))); - - return randomId; - } - - private Set 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 index 00000000..0a0b6249 --- /dev/null +++ b/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeTestBase.java @@ -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 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 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 index 00000000..a417e6f9 --- /dev/null +++ b/src/test/java/de/juplo/kafka/chat/backend/domain/ChatHomeWithShardsTestBase.java @@ -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 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 index 00000000..ff82986a --- /dev/null +++ b/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/ShardedChatHomeTest.java @@ -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 }; + } + } +} diff --git a/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHomeTest.java b/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHomeTest.java index e45f1a5e..1e5f0d4c 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHomeTest.java +++ b/src/test/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHomeTest.java @@ -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 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 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()); + } } } -- 2.20.1