From 404a94c307740cdd9b4e7d3fcb25381fbe60f024 Mon Sep 17 00:00:00 2001 From: Christian Koop Date: Tue, 15 Nov 2022 22:47:39 +0100 Subject: [PATCH] Move from MockBukkit to Mockito in automated tests MockBukkit is not able to mock all of Bukkit's API and broke with a change in PaperMC causing all our current tests to fail. It is also version dependant. But with Mockito you have to do everything manually right now. No helping functionality (like creating a new mock player which automatically will be returned in `Bukkit#getOnlinePlayers()`) I took this opportunity to learn a bit about Mocking in Bukkit and decided on Mockito. It looks like we could easily write our own MockBukkit alternative in the future. I am not really happy how `Mockito#verify` works tho. I find it annoying not to be able to directly assert on the calls made to a method. You have to create an InOrder instance first for the mock and in the end verify with `Mockito#times(0)`/`Mockito#never()` and `Mockito#any()` for each argument a method takes, to assert a total of n calls. --- .../bukkit/CompatibleSoundTest.java | 32 -- .../material/CompatibleMaterialTest.java | 88 ----- .../songoda/core/input/ChatPromptTest.java | 127 ------ .../core/locale/LocaleFileManagerTest.java | 30 +- .../songoda/core/utils/LocationUtilsTest.java | 15 +- .../songoda/core/utils/PlayerUtilsTest.java | 365 ++++++++++++------ pom.xml | 20 +- 7 files changed, 284 insertions(+), 393 deletions(-) delete mode 100644 Compatibility/src/test/java/com/songoda/core/compatibility/bukkit/CompatibleSoundTest.java delete mode 100644 Core/src/test/java/com/songoda/core/compatibility/material/CompatibleMaterialTest.java delete mode 100644 Core/src/test/java/com/songoda/core/input/ChatPromptTest.java diff --git a/Compatibility/src/test/java/com/songoda/core/compatibility/bukkit/CompatibleSoundTest.java b/Compatibility/src/test/java/com/songoda/core/compatibility/bukkit/CompatibleSoundTest.java deleted file mode 100644 index 901d1661..00000000 --- a/Compatibility/src/test/java/com/songoda/core/compatibility/bukkit/CompatibleSoundTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.songoda.core.compatibility.bukkit; - -import be.seeseemelk.mockbukkit.MockBukkit; -import com.songoda.core.compatibility.CompatibleSound; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertNotNull; - -class CompatibleSoundTest { - @BeforeEach - void setUp() { - MockBukkit.mock(); - } - - @AfterEach - void tearDown() { - MockBukkit.unmock(); - } - - @Test - @Disabled("CompatibleSound class needs some work beforehand") - void getSound() { - for (CompatibleSound compatibleSound : CompatibleSound.values()) { - assertNotNull(compatibleSound.getSound()); - - // compatibleSound.usesCompatibility() - } - } -} diff --git a/Core/src/test/java/com/songoda/core/compatibility/material/CompatibleMaterialTest.java b/Core/src/test/java/com/songoda/core/compatibility/material/CompatibleMaterialTest.java deleted file mode 100644 index 623c2aea..00000000 --- a/Core/src/test/java/com/songoda/core/compatibility/material/CompatibleMaterialTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.songoda.core.compatibility.material; - -import be.seeseemelk.mockbukkit.MockBukkit; -import com.songoda.core.compatibility.CompatibleMaterial; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; - -class CompatibleMaterialTest { - @BeforeEach - void setUp() { - MockBukkit.mock(); - } - - @AfterEach - void tearDown() { - MockBukkit.unmock(); - } - - @Test - void getMaterialForNull() { - assertNull(CompatibleMaterial.getMaterial((Material) null)); - assertNull(CompatibleMaterial.getMaterial((ItemStack) null)); - } - - @Disabled("This test causes issues and is version dependent") - @Test - void getMaterialForAllBukkitMaterials() { - Map returnedMaterials = new HashMap<>(Material.values().length); - for (Material bukkitMaterial : Material.values()) { - CompatibleMaterial compatibleMaterial = CompatibleMaterial.getMaterial(bukkitMaterial); - - if (bukkitMaterial.name().startsWith("LEGACY_")) { - assertNull(compatibleMaterial); - continue; - } - assertNotNull(compatibleMaterial, () -> "Could not get an CompatibleMaterial for Material." + bukkitMaterial.name()); - assertEquals(bukkitMaterial, compatibleMaterial.getMaterial()); - assertEquals(compatibleMaterial, CompatibleMaterial.getMaterial(bukkitMaterial.name())); - - assertFalse(returnedMaterials.containsKey(compatibleMaterial), - () -> String.format("Assertion failed when converting Material.%s to CompatibleMaterial.%s: " + - "CompatibleMaterial.%1$s has already been returned for Material.%3$s previously", - bukkitMaterial.name(), - compatibleMaterial.name(), - returnedMaterials.get(compatibleMaterial).name() - )); - - assertEquals(bukkitMaterial.isAir(), compatibleMaterial.isAir(), getMaterialPropertyAssertionError(compatibleMaterial, "Air")); - assertEquals(bukkitMaterial.isBlock(), compatibleMaterial.isBlock(), getMaterialPropertyAssertionError(compatibleMaterial, "Block")); - assertEquals(bukkitMaterial.isBurnable(), compatibleMaterial.isBurnable(), getMaterialPropertyAssertionError(compatibleMaterial, "Burnable")); - assertEquals(bukkitMaterial.isEdible(), compatibleMaterial.isEdible(), getMaterialPropertyAssertionError(compatibleMaterial, "Edible")); - assertEquals(bukkitMaterial.isFlammable(), compatibleMaterial.isFlammable(), getMaterialPropertyAssertionError(compatibleMaterial, "Flammable")); - assertEquals(bukkitMaterial.isFuel(), compatibleMaterial.isFuel(), getMaterialPropertyAssertionError(compatibleMaterial, "Fuel")); - assertEquals(bukkitMaterial.isInteractable(), compatibleMaterial.isInteractable(), getMaterialPropertyAssertionError(compatibleMaterial, "Interactable")); - assertEquals(bukkitMaterial.isItem(), compatibleMaterial.isItem(), getMaterialPropertyAssertionError(compatibleMaterial, "Item")); - assertEquals(bukkitMaterial.isOccluding(), compatibleMaterial.isOccluding(), getMaterialPropertyAssertionError(compatibleMaterial, "Occluding")); - assertEquals(bukkitMaterial.isSolid(), compatibleMaterial.isSolid(), getMaterialPropertyAssertionError(compatibleMaterial, "Solid")); - assertEquals(bukkitMaterial.isTransparent(), compatibleMaterial.isTransparent(), getMaterialPropertyAssertionError(compatibleMaterial, "Transparent")); - - assertFalse(compatibleMaterial.usesCompatibility()); - assertFalse(compatibleMaterial.usesData()); - assertEquals(-1, compatibleMaterial.getData()); - - ItemStack compatibleItem = compatibleMaterial.getItem(); - assertEquals(bukkitMaterial, compatibleItem.getType()); - assertEquals(compatibleMaterial, CompatibleMaterial.getMaterial(compatibleItem)); - - returnedMaterials.put(compatibleMaterial, bukkitMaterial); - } - } - - private Supplier getMaterialPropertyAssertionError(CompatibleMaterial compatibleMaterial, String propertyName) { - return () -> String.format("Expected CompatibleMaterial.%s to be '%s'", compatibleMaterial.name(), propertyName); - } -} diff --git a/Core/src/test/java/com/songoda/core/input/ChatPromptTest.java b/Core/src/test/java/com/songoda/core/input/ChatPromptTest.java deleted file mode 100644 index 06d8e22f..00000000 --- a/Core/src/test/java/com/songoda/core/input/ChatPromptTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.songoda.core.input; - -import be.seeseemelk.mockbukkit.MockBukkit; -import be.seeseemelk.mockbukkit.MockPlugin; -import be.seeseemelk.mockbukkit.ServerMock; -import be.seeseemelk.mockbukkit.entity.PlayerMock; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@Disabled("BukkitMock seems to cause some troubles here, skipping for now") -class ChatPromptTest { - private final String inputMsg = "&eInput-Message"; - - private ServerMock server; - private MockPlugin plugin; - private PlayerMock player; - - @BeforeEach - void setUp() { - this.server = MockBukkit.mock(); - this.plugin = MockBukkit.createMockPlugin(); - this.player = this.server.addPlayer(); - } - - @AfterEach - void tearDown() { - MockBukkit.unmock(); - } - - @Test - void showPrompt() throws InterruptedException { - List chatInputs = new ArrayList<>(1); - - ChatPrompt.showPrompt(this.plugin, this.player, event -> { - assertEquals(this.player, event.getPlayer()); - - chatInputs.add(event.getMessage()); - }); - - this.player.chat(this.inputMsg); - Thread.sleep(1000); - // this.server.getScheduler().waitAsyncTasksFinished() // does not wait for async events - - String playerReceivedMsg = this.player.nextMessage(); - - assertNotNull(playerReceivedMsg); - assertTrue(playerReceivedMsg.endsWith(this.inputMsg)); - - assertEquals(1, chatInputs.size()); - assertEquals(this.inputMsg, chatInputs.get(0)); - } - - /* FIXME: Something is still running in the background and prevents the test from finishing */ - @Disabled("Scheduling mock seems bugged, skipping for now") - @Test - void showPromptWithTimeout() { - AtomicBoolean calledOnClose = new AtomicBoolean(false); - - ChatPrompt.showPrompt(this.plugin, this.player, event -> { - }) - .setOnClose(() -> calledOnClose.set(true)) - .setTimeOut(this.player, 40); - - this.server.getScheduler().performTicks(40); - - String playerReceivedMsg = this.player.nextMessage(); - - assertNotNull(playerReceivedMsg); - assertTrue(playerReceivedMsg.contains("timed out")); - - this.server.getScheduler().performOneTick(); - assertTrue(calledOnClose.get()); - } - - @Test - void cancelPrompt() { - AtomicBoolean calledOnCancel = new AtomicBoolean(false); - AtomicBoolean calledHandler = new AtomicBoolean(false); - - ChatPrompt prompt = ChatPrompt.showPrompt(plugin, player, (event) -> calledHandler.set(true)); - prompt.setOnCancel(() -> calledOnCancel.set(true)); - - this.server.dispatchCommand(player, "cancel"); - // this.player.chat("/cancel"); -// Thread.sleep(1000); - // this.server.getScheduler().waitAsyncTasksFinished() // does not wait for async events - - System.out.println(this.player.nextMessage()); - -// assertTrue(player.nextMessage().endsWith("/cancel")); - - assertTrue(calledOnCancel.get()); - assertFalse(calledHandler.get()); - } - - @Test - void isRegistered() { - assertFalse(ChatPrompt.isRegistered(this.player)); - - ChatPrompt.showPrompt(this.plugin, this.player, (event) -> { - }); - - assertTrue(ChatPrompt.isRegistered(this.player)); - } - - @Test - void unregister() { - assertFalse(ChatPrompt.unregister(this.player)); - - ChatPrompt.showPrompt(this.plugin, this.player, (event) -> { - }); - - assertTrue(ChatPrompt.unregister(this.player)); - assertFalse(ChatPrompt.unregister(this.player)); - } -} diff --git a/Core/src/test/java/com/songoda/core/locale/LocaleFileManagerTest.java b/Core/src/test/java/com/songoda/core/locale/LocaleFileManagerTest.java index a5a503b7..b6966b65 100644 --- a/Core/src/test/java/com/songoda/core/locale/LocaleFileManagerTest.java +++ b/Core/src/test/java/com/songoda/core/locale/LocaleFileManagerTest.java @@ -1,32 +1,44 @@ package com.songoda.core.locale; -import be.seeseemelk.mockbukkit.MockBukkit; -import be.seeseemelk.mockbukkit.MockPlugin; import com.songoda.core.http.MockHttpClient; import com.songoda.core.http.MockHttpResponse; +import org.bukkit.plugin.Plugin; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.List; - +import java.util.Objects; class LocaleFileManagerTest { private final byte[] validIndexFile = ("# This is a comment\n\nen_US.lang\nen.yml\nde.txt\n").getBytes(StandardCharsets.UTF_8); + private File testDirectory; + + @BeforeEach + void setUp() throws IOException { + this.testDirectory = Files.createTempDirectory("SongodaCore-LocaleFileManagerTest").toFile(); + this.testDirectory.deleteOnExit(); + } + @AfterEach - void tearDown() { - MockBukkit.unmock(); + void tearDown() throws IOException { + for (File file : Objects.requireNonNull(this.testDirectory.listFiles())) { + Files.deleteIfExists(file.toPath()); + } + Files.deleteIfExists(this.testDirectory.toPath()); } @Test void downloadMissingTranslations_EmptyTargetDir() throws IOException { - MockBukkit.mock(); - MockPlugin plugin = MockBukkit.createMockPlugin(); + Plugin plugin = Mockito.mock(Plugin.class); + Mockito.when(plugin.getDataFolder()).thenReturn(this.testDirectory); MockHttpClient httpClient = new MockHttpClient(new MockHttpResponse(200, this.validIndexFile)); LocaleFileManager localeFileManager = new LocaleFileManager(httpClient, "test"); @@ -51,8 +63,8 @@ class LocaleFileManagerTest { @Test void downloadMissingTranslations() throws IOException { - MockBukkit.mock(); - MockPlugin plugin = MockBukkit.createMockPlugin(); + Plugin plugin = Mockito.mock(Plugin.class); + Mockito.when(plugin.getDataFolder()).thenReturn(this.testDirectory); Files.createDirectories(plugin.getDataFolder().toPath()); Files.createFile(new File(plugin.getDataFolder(), "en_US.lang").toPath()); diff --git a/Core/src/test/java/com/songoda/core/utils/LocationUtilsTest.java b/Core/src/test/java/com/songoda/core/utils/LocationUtilsTest.java index 9fc10215..3af6cab8 100644 --- a/Core/src/test/java/com/songoda/core/utils/LocationUtilsTest.java +++ b/Core/src/test/java/com/songoda/core/utils/LocationUtilsTest.java @@ -1,9 +1,10 @@ package com.songoda.core.utils; -import be.seeseemelk.mockbukkit.WorldMock; import org.bukkit.Location; +import org.bukkit.World; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -13,12 +14,20 @@ class LocationUtilsTest { void isLocationMatching() { assertTrue(LocationUtils.isLocationMatching( new Location(null, 10, 20, 30), - new Location(new WorldMock(), 10.25, 20.5, 30.75) + new Location(Mockito.mock(World.class), 10.25, 20.5, 30.75) + )); + assertTrue(LocationUtils.isLocationMatching( + new Location(null, 10, 20, 30), + new Location(null, 10.25, 20.5, 30.75) )); assertFalse(LocationUtils.isLocationMatching( new Location(null, 10, 20, 30), - new Location(new WorldMock(), -10.25, 20.5, 30.75) + new Location(Mockito.mock(World.class), -10.25, 20.5, 30.75) + )); + assertFalse(LocationUtils.isLocationMatching( + new Location(Mockito.mock(World.class), 10, 20, 30), + new Location(null, -10.25, 20.5, 30.75) )); } diff --git a/Core/src/test/java/com/songoda/core/utils/PlayerUtilsTest.java b/Core/src/test/java/com/songoda/core/utils/PlayerUtilsTest.java index d7bcb1c2..99d19cc8 100644 --- a/Core/src/test/java/com/songoda/core/utils/PlayerUtilsTest.java +++ b/Core/src/test/java/com/songoda/core/utils/PlayerUtilsTest.java @@ -1,134 +1,143 @@ package com.songoda.core.utils; -import be.seeseemelk.mockbukkit.MockBukkit; -import be.seeseemelk.mockbukkit.ServerMock; -import be.seeseemelk.mockbukkit.entity.PlayerMock; -import org.bukkit.Material; +import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.bukkit.inventory.PlayerInventory; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.mockito.InOrder; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class PlayerUtilsTest { - private ServerMock server; + @Test + void sendMessages_Array() { + Player player = Mockito.mock(Player.class); + PlayerUtils.sendMessages(player, "First message", "Second message"); - @BeforeEach - void setUp() { - this.server = MockBukkit.mock(); - } - - @AfterEach - void tearDown() { - MockBukkit.unmock(); - this.server = null; + InOrder playerInOrder = Mockito.inOrder(player); + playerInOrder.verify(player).sendMessage("First message"); + playerInOrder.verify(player).sendMessage("Second message"); + playerInOrder.verify(player, Mockito.never()).sendMessage(Mockito.anyString()); } @Test - void sendMessages() { - String[] messages = new String[] {"First message", "Second message"}; + void sendMessages_List() { + Player player = Mockito.mock(Player.class); + PlayerUtils.sendMessages(player, Arrays.asList("First message", "Second message")); - PlayerMock player = this.server.addPlayer(); - - PlayerUtils.sendMessages(player, messages); - PlayerUtils.sendMessages(player, Arrays.asList(messages)); - - for (int i = 0; i < 2; ++i) { - assertEquals(messages[0], player.nextMessage()); - assertEquals(messages[1], player.nextMessage()); - } - - assertNull(player.nextMessage()); + InOrder playerInOrder = Mockito.inOrder(player); + playerInOrder.verify(player).sendMessage("First message"); + playerInOrder.verify(player).sendMessage("Second message"); + playerInOrder.verify(player, Mockito.never()).sendMessage(Mockito.anyString()); } - @Disabled("Player#hidePlayer can currently not be mocked") @Test void getVisiblePlayerNames() { - PlayerMock player = this.server.addPlayer("BasePlayer"); - PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer"); - PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer"); + Player player = createMockPlayer("BasePlayer"); + Player visiblePlayer = createMockPlayer("VisiblePlayer"); + Player hiddenPlayer = createMockPlayer("HiddenPlayer"); - player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer); + List result; + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer)); - List result = PlayerUtils.getVisiblePlayerNames(player, null); - assertTrue(result.contains(visiblePlayer.getName())); - assertFalse(result.contains(hiddenPlayer.getName())); - assertFalse(result.contains(player.getName())); + Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false); + Mockito.when(player.canSee(visiblePlayer)).thenReturn(true); - assertEquals(0, PlayerUtils.getVisiblePlayerNames(player, "_").size()); + assertEquals(0, PlayerUtils.getVisiblePlayerNames(player, "_").size()); + + result = PlayerUtils.getVisiblePlayerNames(player, null); + } + + assertTrue(result.contains("VisiblePlayer")); + assertEquals(1, result.size()); } - @Disabled("Player#hidePlayer can currently not be mocked") @Test void getVisiblePlayerDisplayNames() { - PlayerMock player = this.server.addPlayer("BasePlayer"); - PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer"); - PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer"); + Player player = createMockPlayer("BasePlayer"); + Player visiblePlayer = createMockPlayer("VisiblePlayer", "VisibleDisplayName"); + Player hiddenPlayer = createMockPlayer("HiddenPlayer"); - player.setDisplayName("Base"); - visiblePlayer.setDisplayName("Visible"); - hiddenPlayer.setDisplayName("Hidden"); + List result; + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer)); - player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer); + Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false); + Mockito.when(player.canSee(visiblePlayer)).thenReturn(true); - List result = PlayerUtils.getVisiblePlayerDisplayNames(player, null); - assertTrue(result.contains(visiblePlayer.getDisplayName())); - assertFalse(result.contains(hiddenPlayer.getDisplayName())); - assertFalse(result.contains(player.getDisplayName())); + assertEquals(0, PlayerUtils.getVisiblePlayerDisplayNames(player, "A").size()); - assertEquals(0, PlayerUtils.getVisiblePlayerDisplayNames(player, "_").size()); + result = PlayerUtils.getVisiblePlayerDisplayNames(player, null); + } + + assertTrue(result.contains("VisibleDisplayName")); + assertEquals(1, result.size()); } - @Disabled("Player#hidePlayer can currently not be mocked") @Test void getVisiblePlayers() { - PlayerMock player = this.server.addPlayer("BasePlayer"); - PlayerMock visiblePlayer = this.server.addPlayer("VisiblePlayer"); - PlayerMock hiddenPlayer = this.server.addPlayer("HiddenPlayer"); + Player player = createMockPlayer("BasePlayer"); + Player visiblePlayer = createMockPlayer("VisiblePlayer"); + Player hiddenPlayer = createMockPlayer("HiddenPlayer"); - player.hidePlayer(MockBukkit.createMockPlugin(), hiddenPlayer); + Mockito.when(player.canSee(hiddenPlayer)).thenReturn(false); + Mockito.when(player.canSee(visiblePlayer)).thenReturn(true); + + List result; + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(player, visiblePlayer, hiddenPlayer)); + + assertEquals(0, PlayerUtils.getVisiblePlayers(player, "_").size()); + + result = PlayerUtils.getVisiblePlayers(player, null); + } - List result = PlayerUtils.getVisiblePlayers(player, null); assertTrue(result.contains(visiblePlayer)); - assertFalse(result.contains(hiddenPlayer)); - assertFalse(result.contains(player)); - - assertEquals(0, PlayerUtils.getVisiblePlayers(player, "_").size()); + assertEquals(1, result.size()); } @Test void getAllPlayers() { - PlayerMock basePlayer = this.server.addPlayer("BasePlayer"); - this.server.addPlayer("Player_1"); - this.server.addPlayer("Player_2"); - this.server.addPlayer("Player3"); + Player basePlayer = createMockPlayer("BasePlayer"); + Player player1 = createMockPlayer("Player_1"); + Player player2 = createMockPlayer("Player_2"); + Player player3 = createMockPlayer("Player3"); - List result = PlayerUtils.getAllPlayers(basePlayer, ""); - assertEquals(3, result.size()); - assertFalse(result.contains(basePlayer.getName())); + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + server.when(Bukkit::getOnlinePlayers).thenReturn(Arrays.asList(basePlayer, player1, player2, player3)); - assertTrue(PlayerUtils.getAllPlayers(basePlayer, "_").isEmpty()); - assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "Player_").size()); + assertEquals(0, PlayerUtils.getVisiblePlayers(basePlayer, "_").size()); + + List result = PlayerUtils.getAllPlayers(basePlayer, ""); + assertFalse(result.contains(basePlayer.getName())); + assertEquals(3, result.size()); + + assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "_").size()); + assertEquals(0, PlayerUtils.getAllPlayers(basePlayer, "Player_").size()); + } } @Disabled("Disabled for now as the implementations seems to be faulty") @Test void getAllPlayersDisplay() { - PlayerMock basePlayer = this.server.addPlayer("BasePlayer"); - this.server.addPlayer("Player_1"); - this.server.addPlayer("Player_2"); - this.server.addPlayer("Player3"); + Player basePlayer = createMockPlayer("BasePlayer"); + createMockPlayer("Player_1"); + createMockPlayer("Player_2"); + createMockPlayer("Player3"); List result = PlayerUtils.getAllPlayersDisplay(basePlayer, ""); assertEquals(3, result.size()); @@ -141,13 +150,9 @@ class PlayerUtilsTest { @Disabled("Disabled for now as the implementations seems to be faulty") @Test void findPlayer() { - Player p3 = this.server.addPlayer("Player"); - Player p1 = this.server.addPlayer("Player_1"); - Player p2 = this.server.addPlayer("_Player_2"); - - p1.setDisplayName("p1"); - p2.setDisplayName("p2"); - p3.setDisplayName("p3"); + Player p3 = createMockPlayer("Player", "p3"); + Player p1 = createMockPlayer("Player_1", "p1"); + Player p2 = createMockPlayer("_Player_2", "p2"); assertEquals(p1, PlayerUtils.findPlayer("Player_")); assertEquals(p2, PlayerUtils.findPlayer("_Play")); @@ -160,73 +165,185 @@ class PlayerUtilsTest { } @Test - void getRandomPlayer() { - assertNull(PlayerUtils.getRandomPlayer()); - - for (int i = 0; i < 10; ++i) { - this.server.addPlayer(String.valueOf(i)); + void getRandomPlayer_NoneOnline() { + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + server.when(Bukkit::getOnlinePlayers).thenReturn(Collections.emptyList()); + assertNull(PlayerUtils.getRandomPlayer()); } + } - Set returnedPlayers = new HashSet<>(); - for (int i = 0; i < 50; ++i) { - if (returnedPlayers.size() >= 5) { - break; + @Test + void getRandomPlayer() { + try (MockedStatic server = Mockito.mockStatic(Bukkit.class)) { + List players = new ArrayList<>(10); + for (int i = 0; i < 10; ++i) { + Player player = createMockPlayer("Player_" + i); + players.add(player); } - returnedPlayers.add(PlayerUtils.getRandomPlayer()); - } + server.when(Bukkit::getOnlinePlayers).thenReturn(players); - assertTrue(returnedPlayers.size() >= 5); + Set returnedPlayers = new HashSet<>(); + for (int i = 0; i < 50; ++i) { + if (returnedPlayers.size() >= 5) { + break; + } + + returnedPlayers.add(PlayerUtils.getRandomPlayer()); + } + + assertTrue(returnedPlayers.size() >= 5); + } } @Test void giveItem() { - Player player = this.server.addPlayer(); + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + InOrder inventoryInOrder = Mockito.inOrder(inventory); - PlayerUtils.giveItem(player, new ItemStack(Material.STONE)); - assertTrue(player.getInventory().contains(Material.STONE, 1)); + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); - PlayerUtils.giveItem(player, new ItemStack(Material.GRASS_BLOCK), new ItemStack(Material.GRASS_BLOCK)); - assertTrue(player.getInventory().contains(Material.GRASS_BLOCK, 2)); + ItemStack itemToAdd = Mockito.mock(ItemStack.class); - PlayerUtils.giveItem(player, Arrays.asList(new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS))); - assertTrue(player.getInventory().contains(Material.WHEAT_SEEDS, 2)); + PlayerUtils.giveItem(player, itemToAdd); + inventoryInOrder.verify(inventory).addItem(itemToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); } @Test - void giveItemOnFullInventory() { - PlayerMock player = this.server.addPlayer(); + void giveItem_Array() { + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + InOrder inventoryInOrder = Mockito.inOrder(inventory); - fillInventory(player); + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); - int entityCount = this.server.getEntities().size(); - PlayerUtils.giveItem(player, new ItemStack(Material.STONE)); - assertEquals(entityCount + 1, this.server.getEntities().size()); + ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)}; - entityCount = this.server.getEntities().size(); - PlayerUtils.giveItem(player, new ItemStack(Material.GRASS_BLOCK), new ItemStack(Material.GRASS_BLOCK)); - assertEquals(entityCount + 2, this.server.getEntities().size()); + PlayerUtils.giveItem(player, itemsToAdd); + inventoryInOrder.verify(inventory).addItem(itemsToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); + } - entityCount = this.server.getEntities().size(); - PlayerUtils.giveItem(player, Arrays.asList(new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS), new ItemStack(Material.WHEAT_SEEDS))); - assertEquals(entityCount + 3, this.server.getEntities().size()); + @Test + void giveItem_List() { + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + InOrder inventoryInOrder = Mockito.inOrder(inventory); + + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); + + ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)}; + + PlayerUtils.giveItem(player, Arrays.asList(itemsToAdd)); + inventoryInOrder.verify(inventory).addItem(itemsToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); + } + + @Test + void giveItem_FullInventory() { + ItemStack itemToAdd = Mockito.mock(ItemStack.class); + + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + Mockito.when(inventory.addItem(itemToAdd)).thenReturn(new HashMap() {{ + put(0, itemToAdd); + }}); + InOrder inventoryInOrder = Mockito.inOrder(inventory); + + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); + + World world = Mockito.mock(World.class); + InOrder worldInOrder = Mockito.inOrder(world); + Mockito.when(player.getWorld()).thenReturn(world); + + PlayerUtils.giveItem(player, itemToAdd); + + inventoryInOrder.verify(inventory).addItem(itemToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); + + worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemToAdd)); + worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); + } + + @Test + void giveItem_FullInventory_Array() { + ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)}; + + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + Mockito.when(inventory.addItem(Mockito.any())).thenReturn(new HashMap() {{ + put(0, itemsToAdd[0]); + put(1, itemsToAdd[1]); + }}); + InOrder inventoryInOrder = Mockito.inOrder(inventory); + + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); + + World world = Mockito.mock(World.class); + InOrder worldInOrder = Mockito.inOrder(world); + Mockito.when(player.getWorld()).thenReturn(world); + + PlayerUtils.giveItem(player, itemsToAdd); + inventoryInOrder.verify(inventory).addItem(itemsToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); + + worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[0])); + worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[1])); + worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); + } + + @Test + void giveItem_FullInventory_List() { + ItemStack[] itemsToAdd = new ItemStack[] {Mockito.mock(ItemStack.class), Mockito.mock(ItemStack.class)}; + + PlayerInventory inventory = Mockito.mock(PlayerInventory.class); + Mockito.when(inventory.addItem(Mockito.any())).thenReturn(new HashMap() {{ + put(0, itemsToAdd[0]); + put(1, itemsToAdd[1]); + }}); + InOrder inventoryInOrder = Mockito.inOrder(inventory); + + Player player = createMockPlayer("Player"); + Mockito.when(player.getInventory()).thenReturn(inventory); + Mockito.when(player.isOnline()).thenReturn(true); + + World world = Mockito.mock(World.class); + InOrder worldInOrder = Mockito.inOrder(world); + Mockito.when(player.getWorld()).thenReturn(world); + + PlayerUtils.giveItem(player, Arrays.asList(itemsToAdd)); + inventoryInOrder.verify(inventory).addItem(itemsToAdd); + inventoryInOrder.verify(inventory, Mockito.never()).addItem(Mockito.any()); + + worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[0])); + worldInOrder.verify(world).dropItemNaturally(Mockito.any(), Mockito.eq(itemsToAdd[1])); + worldInOrder.verify(world, Mockito.never()).dropItemNaturally(Mockito.any(), Mockito.any()); } @Disabled("Test is incomplete") @Test void getNumberFromPermission() { - Player player = this.server.addPlayer(); + Player player = createMockPlayer("Player"); assertEquals(-1, PlayerUtils.getNumberFromPermission(player, "example.plugin.feature", -1)); } - private void fillInventory(Player player) { - ItemStack[] contents = new ItemStack[player.getInventory().getContents().length]; + private Player createMockPlayer(String name) { + return createMockPlayer(name, name); + } - for (int i = 0; i < contents.length; ++i) { - contents[i] = new ItemStack(Material.BARRIER); - } + private Player createMockPlayer(String name, String displayName) { + Player player = Mockito.mock(Player.class); + Mockito.when(player.getName()).thenReturn(name); + Mockito.when(player.getDisplayName()).thenReturn(displayName); - player.getInventory().setContents(contents); + return player; } } diff --git a/pom.xml b/pom.xml index 46e63f70..2c4e18d0 100644 --- a/pom.xml +++ b/pom.xml @@ -196,20 +196,20 @@ test - - - - - - - - com.github.seeseemelk - MockBukkit-v1.19 - 2.120.1 + org.mockito + mockito-inline + 4.9.0 test + + + + + + + org.pitest pitest-maven