From e764522a710361cc34c26e22e715ee4d81a8039e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Jul 2026 09:34:48 +0000 Subject: [PATCH] [Tests] Improve coverage for ItemBuilder, Database, and LocalizationManager - ItemBuilderSectionTest: Add tests for player/skull path, spawner mob type, potion section parsing, banner pattern parsing, item flags with value assertion, custom model data, display name, and lore - DatabaseAdditionalTest: Add non-blocking initialization tests using CompletableFuture-based synchronization, double-shutdown safety, accessor tests, and tableExists negative case - LocalizationManagerTest: Add PAPI hook integration tests (single message and list variants), PAPI-absent and no-Bukkit-player branch tests, broadcastMessage tests covering loaded/unloaded/no-player paths with mockStatic Bukkit, audience player-not-found fallback, missing locale throws, and section locale fallback Co-Authored-By: Claude Opus 4.6 Claude-Session: https://claude.ai/code/session_01KbyV2e3QBZ8qCTa5VSFaBy --- .../item/impl/ItemBuilderSectionTest.java | 102 +++++++++ .../database/DatabaseAdditionalTest.java | 109 +++++++++ .../localization/LocalizationManagerTest.java | 208 ++++++++++++++++++ 3 files changed, 419 insertions(+) diff --git a/src/test/java/com/diamonddagger590/mccore/builder/item/impl/ItemBuilderSectionTest.java b/src/test/java/com/diamonddagger590/mccore/builder/item/impl/ItemBuilderSectionTest.java index 7022e0e..c2e24ff 100644 --- a/src/test/java/com/diamonddagger590/mccore/builder/item/impl/ItemBuilderSectionTest.java +++ b/src/test/java/com/diamonddagger590/mccore/builder/item/impl/ItemBuilderSectionTest.java @@ -5,6 +5,7 @@ import com.diamonddagger590.mccore.testing.TestCorePlugin; import dev.dejvokep.boostedyaml.block.implementation.Section; import org.bukkit.Material; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemType; import org.junit.jupiter.api.AfterEach; @@ -13,12 +14,17 @@ import org.junit.jupiter.api.Test; import org.mockbukkit.mockbukkit.MockBukkit; +import dev.dejvokep.boostedyaml.route.Route; + import java.util.Collections; +import java.util.List; import java.util.Set; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -247,4 +253,100 @@ void copyConstructor_copiesBuilderState_fromSource() { ItemBuilder copy = ItemBuilder.from(source.asItemStack()); assertNotNull(copy); } + + @Test + @DisplayName("Given a section with a non-empty player field, when from(Section) is called, then skull builder path is invoked") + void fromSection_invokesSkullBuilder_whenPlayerIsNonEmpty() { + Section section = createMinimalSection(); + when(section.getString(eq(ItemBuilderConfigurationKeys.MATERIAL), eq("stone"))).thenReturn("player_head"); + when(section.getString(eq(ItemBuilderConfigurationKeys.PLAYER), eq(""))).thenReturn("Notch"); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with a mob type, when from(Section) is called, then spawner builder path is invoked") + void fromSection_invokesSpawnerBuilder_whenMobTypeProvided() { + Section section = createMinimalSection(); + when(section.getString(eq(ItemBuilderConfigurationKeys.MATERIAL), eq("stone"))).thenReturn("spawner"); + when(section.getString(eq(ItemBuilderConfigurationKeys.MOB_TYPE), eq(""))).thenReturn("zombie"); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with potions, when from(Section) is called, then potion builder path is invoked") + void fromSection_invokesPotionBuilder_whenPotionSectionProvided() { + Section section = createMinimalSection(); + when(section.getString(eq(ItemBuilderConfigurationKeys.MATERIAL), eq("stone"))).thenReturn("potion"); + + Section potionSection = mock(Section.class); + when(section.getSection(eq(ItemBuilderConfigurationKeys.POTION_HEADER))).thenReturn(potionSection); + when(potionSection.getRoutesAsStrings(false)).thenReturn(Set.of("speed")); + when(potionSection.getInt(any(Route.class), eq(60))).thenReturn(200); + when(potionSection.getInt(any(Route.class), eq(1))).thenReturn(2); + when(potionSection.getBoolean(any(Route.class), eq(false))).thenReturn(false); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with banner patterns, when from(Section) is called, then pattern builder path is invoked") + void fromSection_invokesPatternBuilder_whenPatternSectionProvided() { + Section section = createMinimalSection(); + when(section.getString(eq(ItemBuilderConfigurationKeys.MATERIAL), eq("stone"))).thenReturn("white_banner"); + + Section patternSection = mock(Section.class); + when(section.getSection(eq(ItemBuilderConfigurationKeys.PATTERN_HEADER))).thenReturn(patternSection); + when(patternSection.getRoutesAsStrings(false)).thenReturn(Set.of("stripe_top")); + when(patternSection.getString("stripe_top", "white")).thenReturn("red"); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with item flags, when from(Section) is called, then item flags are applied") + void fromSection_appliesItemFlags_whenItemFlagsProvided() { + Section section = createMinimalSection(); + when(section.getStringList(eq(ItemBuilderConfigurationKeys.ITEM_FLAGS))).thenReturn(List.of("HIDE_ENCHANTS")); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + ItemStack stack = result.asItemStack(); + assertTrue(stack.getItemFlags().contains(ItemFlag.HIDE_ENCHANTS)); + } + + @Test + @DisplayName("Given a section with custom model data, when from(Section) is called, then custom model data is set") + void fromSection_setsCustomModelData_whenProvided() { + Section section = createMinimalSection(); + when(section.getInt(eq(ItemBuilderConfigurationKeys.CUSTOM_MODEL_DATA), eq(-1))).thenReturn(42); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with display name, when from(Section) is called, then completes without error") + void fromSection_completesWithoutError_whenNameProvided() { + Section section = createMinimalSection(); + when(section.getString(eq(ItemBuilderConfigurationKeys.NAME), eq(""))).thenReturn("Custom Name"); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } + + @Test + @DisplayName("Given a section with lore, when from(Section) is called, then completes without error") + void fromSection_completesWithoutError_whenLoreProvided() { + Section section = createMinimalSection(); + when(section.getStringList(eq(ItemBuilderConfigurationKeys.LORE_ROUTE))).thenReturn(List.of("Line 1", "Line 2")); + + ItemBuilder result = assertDoesNotThrow(() -> ItemBuilder.from(section)); + assertNotNull(result); + } } diff --git a/src/test/java/com/diamonddagger590/mccore/database/DatabaseAdditionalTest.java b/src/test/java/com/diamonddagger590/mccore/database/DatabaseAdditionalTest.java index 761ac5a..08b67c3 100644 --- a/src/test/java/com/diamonddagger590/mccore/database/DatabaseAdditionalTest.java +++ b/src/test/java/com/diamonddagger590/mccore/database/DatabaseAdditionalTest.java @@ -20,8 +20,10 @@ import java.sql.SQLException; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.logging.Logger; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -260,6 +262,113 @@ protected boolean blockMainThreadOnStart() { } } + @Test + @DisplayName("Given a non-blocking database with custom functions, when initializeDatabase is called, then functions are invoked asynchronously") + void initializeDatabase_invokesCustomFunctions_whenNonBlocking() throws Exception { + setupDriverRegistry(); + + NonBlockingTestDatabase database = new NonBlockingTestDatabase(plugin); + CompletableFuture createDone = new CompletableFuture<>(); + CompletableFuture updateDone = new CompletableFuture<>(); + + database.addCreateTableFunction(db -> { + CompletableFuture future = new CompletableFuture<>(); + db.getDatabaseExecutorService().submit(() -> { + future.complete(null); + createDone.complete(null); + }); + return future; + }); + database.addUpdateTableFunction(db -> { + CompletableFuture future = new CompletableFuture<>(); + db.getDatabaseExecutorService().submit(() -> { + future.complete(null); + updateDone.complete(null); + }); + return future; + }); + + try { + database.initializeDatabase(); + createDone.get(5, TimeUnit.SECONDS); + updateDone.get(5, TimeUnit.SECONDS); + assertTrue(createDone.isDone(), "Create table function should have been called"); + assertTrue(updateDone.isDone(), "Update table function should have been called"); + } finally { + database.shutdown(); + } + } + + @Test + @DisplayName("Given a non-blocking database, when initializeDatabase is called, then core tables are created") + void initializeDatabase_createsTables_whenNonBlocking() throws Exception { + setupDriverRegistry(); + + NonBlockingTestDatabase database = new NonBlockingTestDatabase(plugin); + CompletableFuture tablesReady = new CompletableFuture<>(); + database.addUpdateTableFunction(db -> { + CompletableFuture future = new CompletableFuture<>(); + db.getDatabaseExecutorService().submit(() -> { + future.complete(null); + tablesReady.complete(null); + }); + return future; + }); + try { + database.initializeDatabase(); + tablesReady.get(5, TimeUnit.SECONDS); + + Connection conn = database.getConnection(); + assertTrue(database.tableExists(conn, "table_history")); + conn.close(); + } finally { + database.shutdown(); + } + } + + @Test + @DisplayName("Given an initialized database, when shutdown is called twice, then no error occurs") + void shutdown_noError_whenCalledTwice() throws Exception { + setupDriverRegistry(); + + InMemoryTestDatabase database = new InMemoryTestDatabase(plugin); + database.initializeDatabase(); + database.shutdown(); + assertDoesNotThrow(database::shutdown); + } + + @Test + @DisplayName("Given an initialized database, when getDatabaseDriverType is called, then returns the configured type") + void getDatabaseDriverType_returnsConfiguredType() { + InMemoryTestDatabase database = new InMemoryTestDatabase(plugin); + assertEquals(DatabaseDriverType.SQLITE, database.getDatabaseDriverType()); + database.getDatabaseExecutorService().shutdownNow(); + } + + @Test + @DisplayName("Given an initialized database, when getDatabaseExecutorService is called, then returns non-null executor") + void getDatabaseExecutorService_returnsNonNullExecutor() { + InMemoryTestDatabase database = new InMemoryTestDatabase(plugin); + assertNotNull(database.getDatabaseExecutorService()); + database.getDatabaseExecutorService().shutdownNow(); + } + + @Test + @DisplayName("Given an initialized database, when tableExists is called for non-existent table, then returns false") + void tableExists_returnsFalse_whenTableDoesNotExist() throws Exception { + setupDriverRegistry(); + + InMemoryTestDatabase database = new InMemoryTestDatabase(plugin); + try { + database.initializeDatabase(); + Connection conn = database.getConnection(); + assertFalse(database.tableExists(conn, "non_existent_table")); + conn.close(); + } finally { + database.shutdown(); + } + } + static class LeakDetectionTestDatabase extends Database { private static final Credentials CREDENTIALS = new Credentials("", 0, "", "", ""); private static final ConnectionDetails CONNECTION_DETAILS = new ConnectionDetails(5000, 300000, 600000, 2, 10, 30000); diff --git a/src/test/java/com/diamonddagger590/mccore/localization/LocalizationManagerTest.java b/src/test/java/com/diamonddagger590/mccore/localization/LocalizationManagerTest.java index 37fc2ec..9041c86 100644 --- a/src/test/java/com/diamonddagger590/mccore/localization/LocalizationManagerTest.java +++ b/src/test/java/com/diamonddagger590/mccore/localization/LocalizationManagerTest.java @@ -10,6 +10,7 @@ import com.diamonddagger590.mccore.registry.manager.CoreManagerKey; import com.diamonddagger590.mccore.registry.manager.ManagerKey; import com.diamonddagger590.mccore.registry.manager.ManagerRegistry; +import com.diamonddagger590.mccore.external.papi.CorePapiHook; import com.diamonddagger590.mccore.registry.plugin.PluginHookRegistry; import com.diamonddagger590.mccore.configuration.ReloadableContentManager; import com.diamonddagger590.mccore.setting.PlayerSettingRegistry; @@ -33,6 +34,7 @@ import java.util.Optional; import java.util.UUID; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -787,4 +789,210 @@ void localeChain_unsupportedClientLocale_fallsToEnglish() { assertEquals("English fallback", localizationManager.getLocalizedMessage(player, testRoute)); } + + // --- PAPI hook integration --- + + private void registerPapiHook(CorePapiHook papiHook) { + try { + PluginHookRegistry hookRegistry = RegistryAccess.registryAccess().registry(RegistryKey.PLUGIN_HOOK); + java.lang.reflect.Field hooksField = PluginHookRegistry.class.getDeclaredField("hooks"); + hooksField.setAccessible(true); + @SuppressWarnings("unchecked") + Map, Object> hooks = (Map, Object>) hooksField.get(hookRegistry); + hooks.put(CorePapiHook.class, papiHook); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + @DisplayName("Given PAPI hook is registered and player is online, when getLocalizedMessage(player, route), then PAPI translates message") + void getLocalizedMessage_player_appliesPapiHook_whenAvailable() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Hello %player_name%"); + + UUID uuid = UUID.randomUUID(); + Player bukkitPlayer = mock(Player.class); + when(bukkitPlayer.locale()).thenReturn(Locale.ENGLISH); + TestCorePlayer player = new TestCorePlayer(uuid, mockPlugin, bukkitPlayer); + + CorePapiHook papiHook = mock(CorePapiHook.class); + when(papiHook.translateMessage(bukkitPlayer, "Hello %player_name%")).thenReturn("Hello Steve"); + registerPapiHook(papiHook); + + assertEquals("Hello Steve", localizationManager.getLocalizedMessage(player, testRoute)); + } + + @Test + @DisplayName("Given PAPI hook is registered and player is online, when getLocalizedMessages(player, route), then PAPI translates each line") + void getLocalizedMessages_player_appliesPapiHook_whenAvailable() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getStringList(testRoute)).thenReturn(List.of("Line %player_name%", "Another %player_level%")); + + UUID uuid = UUID.randomUUID(); + Player bukkitPlayer = mock(Player.class); + when(bukkitPlayer.locale()).thenReturn(Locale.ENGLISH); + TestCorePlayer player = new TestCorePlayer(uuid, mockPlugin, bukkitPlayer); + + CorePapiHook papiHook = mock(CorePapiHook.class); + when(papiHook.translateMessage(bukkitPlayer, "Line %player_name%")).thenReturn("Line Steve"); + when(papiHook.translateMessage(bukkitPlayer, "Another %player_level%")).thenReturn("Another 10"); + registerPapiHook(papiHook); + + List result = localizationManager.getLocalizedMessages(player, testRoute); + assertEquals(2, result.size()); + assertEquals("Line Steve", result.get(0)); + assertEquals("Another 10", result.get(1)); + } + + @Test + @DisplayName("Given PAPI hook is absent, when getLocalizedMessage(player, route), then message is returned without PAPI translation") + void getLocalizedMessage_player_noPapiHook_returnsRawMessage() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Hello %player_name%"); + + TestCorePlayer player = createPlayerWithLocale(Locale.ENGLISH); + + assertEquals("Hello %player_name%", localizationManager.getLocalizedMessage(player, testRoute)); + } + + @Test + @DisplayName("Given PAPI hook present but player has no Bukkit player, when getLocalizedMessage(player, route), then message is returned without PAPI translation") + void getLocalizedMessage_player_papiHookPresent_noBukkitPlayer_returnsRawMessage() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Hello %player_name%"); + + TestCorePlayer player = createPlayerWithoutBukkit(); + + CorePapiHook papiHook = mock(CorePapiHook.class); + registerPapiHook(papiHook); + + assertEquals("Hello %player_name%", localizationManager.getLocalizedMessage(player, testRoute)); + } + + // --- broadcastMessage --- + + @Test + @DisplayName("Given no online players, when broadcastMessage is called, then message is sent to console") + void broadcastMessage_sendsToConsole_whenNoOnlinePlayers() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Broadcast!"); + + PlayerManager playerManager = new PlayerManager<>(mockPlugin); + ManagerRegistry managerRegistry = RegistryAccess.registryAccess().registry(RegistryKey.MANAGER); + managerRegistry.register(playerManager); + + org.bukkit.command.ConsoleCommandSender consoleSender = mock(org.bukkit.command.ConsoleCommandSender.class); + try (var mockedBukkit = org.mockito.Mockito.mockStatic(org.bukkit.Bukkit.class)) { + mockedBukkit.when(org.bukkit.Bukkit::getOnlinePlayers).thenReturn(java.util.Collections.emptyList()); + mockedBukkit.when(org.bukkit.Bukkit::getConsoleSender).thenReturn(consoleSender); + + assertDoesNotThrow(() -> localizationManager.broadcastMessage(testRoute)); + org.mockito.Mockito.verify(consoleSender).sendMessage(org.mockito.ArgumentMatchers.anyString()); + } + } + + @Test + @DisplayName("Given an online player with a stored CorePlayer, when broadcastMessage, then uses player's locale chain") + void broadcastMessage_usesPlayerLocaleChain_whenPlayerIsLoaded() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Broadcast msg"); + + UUID uuid = UUID.randomUUID(); + Player bukkitPlayer = mock(Player.class); + when(bukkitPlayer.getUniqueId()).thenReturn(uuid); + when(bukkitPlayer.locale()).thenReturn(Locale.ENGLISH); + + TestCorePlayer corePlayer = new TestCorePlayer(uuid, mockPlugin, bukkitPlayer); + PlayerManager playerManager = new PlayerManager<>(mockPlugin); + playerManager.addPlayer(corePlayer); + ManagerRegistry managerRegistry = RegistryAccess.registryAccess().registry(RegistryKey.MANAGER); + managerRegistry.register(playerManager); + + org.bukkit.command.ConsoleCommandSender consoleSender = mock(org.bukkit.command.ConsoleCommandSender.class); + try (var mockedBukkit = org.mockito.Mockito.mockStatic(org.bukkit.Bukkit.class)) { + mockedBukkit.when(org.bukkit.Bukkit::getOnlinePlayers).thenReturn(List.of(bukkitPlayer)); + mockedBukkit.when(org.bukkit.Bukkit::getConsoleSender).thenReturn(consoleSender); + + assertDoesNotThrow(() -> localizationManager.broadcastMessage(testRoute)); + org.mockito.Mockito.verify(bukkitPlayer).sendMessage(org.mockito.ArgumentMatchers.anyString()); + org.mockito.Mockito.verify(consoleSender).sendMessage(org.mockito.ArgumentMatchers.anyString()); + } + } + + @Test + @DisplayName("Given an online player not stored in PlayerManager, when broadcastMessage, then uses default locale chain") + void broadcastMessage_usesDefaultLocale_whenPlayerNotLoaded() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getString(testRoute)).thenReturn("Default broadcast"); + + UUID uuid = UUID.randomUUID(); + Player bukkitPlayer = mock(Player.class); + when(bukkitPlayer.getUniqueId()).thenReturn(uuid); + + PlayerManager playerManager = new PlayerManager<>(mockPlugin); + ManagerRegistry managerRegistry = RegistryAccess.registryAccess().registry(RegistryKey.MANAGER); + managerRegistry.register(playerManager); + + org.bukkit.command.ConsoleCommandSender consoleSender = mock(org.bukkit.command.ConsoleCommandSender.class); + try (var mockedBukkit = org.mockito.Mockito.mockStatic(org.bukkit.Bukkit.class)) { + mockedBukkit.when(org.bukkit.Bukkit::getOnlinePlayers).thenReturn(List.of(bukkitPlayer)); + mockedBukkit.when(org.bukkit.Bukkit::getConsoleSender).thenReturn(consoleSender); + + assertDoesNotThrow(() -> localizationManager.broadcastMessage(testRoute)); + org.mockito.Mockito.verify(bukkitPlayer).sendMessage("Default broadcast"); + org.mockito.Mockito.verify(consoleSender).sendMessage("Default broadcast"); + } + } + + // --- getLocalizedMessages(Audience, Route) player-not-found branch --- + + @Test + @DisplayName("Given audience is a Player not stored in PlayerManager, when getLocalizedMessages(audience, route), then falls back to default locale") + void getLocalizedMessages_audience_playerNotFound_usesDefault() { + registerEnglishDoc(); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getStringList(testRoute)).thenReturn(List.of("Fallback")); + + UUID uuid = UUID.randomUUID(); + Player bukkitPlayer = mock(Player.class); + when(bukkitPlayer.getUniqueId()).thenReturn(uuid); + + PlayerManager playerManager = new PlayerManager<>(mockPlugin); + RegistryAccess.registryAccess().registry(RegistryKey.MANAGER).register(playerManager); + + List result = localizationManager.getLocalizedMessages(bukkitPlayer, testRoute); + assertEquals(1, result.size()); + assertEquals("Fallback", result.get(0)); + } + + // --- getLocalizedMessages(Route) missing locale branch --- + + @Test + @DisplayName("Given no localizations registered, when getLocalizedMessages(route), then throws") + void getLocalizedMessages_route_throwsWhenNoLocalizations() { + assertThrows(NoLocalizationContainsMessageException.class, + () -> localizationManager.getLocalizedMessages(testRoute)); + } + + // --- getLocalizedSection locale-not-in-map branch --- + + @Test + @DisplayName("Given player's locale is unsupported, when getLocalizedSection(player, route), then falls back to English") + void getLocalizedSection_player_fallsToEnglish_whenClientLocaleUnsupported() { + registerEnglishDoc(); + Section mockSection = mock(Section.class); + when(englishDoc.contains(testRoute)).thenReturn(true); + when(englishDoc.getSection(testRoute)).thenReturn(mockSection); + + TestCorePlayer player = createPlayerWithLocale(Locale.JAPANESE); + assertEquals(mockSection, localizationManager.getLocalizedSection(player, testRoute)); + } }