Explorar o código

more work on command on level up and misc refactoring on unit tests

nossr50 hai 3 semanas
pai
achega
7afdb0ec9c
Modificáronse 20 ficheiros con 705 adicións e 611 borrados
  1. 1 8
      src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java
  2. 1 1
      src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java
  3. 1 1
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  4. 2 5
      src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java
  5. 5 5
      src/main/java/com/gmail/nossr50/listeners/SelfListener.java
  6. 1 2
      src/main/java/com/gmail/nossr50/mcMMO.java
  7. 16 14
      src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java
  8. 1 0
      src/main/java/com/gmail/nossr50/util/skills/SkillTools.java
  9. 96 61
      src/test/java/com/gmail/nossr50/MMOTestEnvironment.java
  10. 268 295
      src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java
  11. 118 74
      src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java
  12. 0 5
      src/test/java/com/gmail/nossr50/config/CommandOnLevelUpConfigTest.java
  13. 3 0
      src/test/java/com/gmail/nossr50/party/PartyManagerTest.java
  14. 10 3
      src/test/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsTest.java
  15. 10 8
      src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java
  16. 43 43
      src/test/java/com/gmail/nossr50/skills/tridents/TridentsTest.java
  17. 41 26
      src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java
  18. 60 60
      src/test/java/com/gmail/nossr50/util/PotionEffectUtilTest.java
  19. 12 0
      src/test/java/com/gmail/nossr50/util/TestPlayerMock.java
  20. 16 0
      src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java

+ 1 - 8
src/main/java/com/gmail/nossr50/config/CommandOnLevelUpConfig.java

@@ -1,20 +1,13 @@
 package com.gmail.nossr50.config;
 
 import com.gmail.nossr50.commands.levelup.LevelUpCommand;
-import com.gmail.nossr50.commands.levelup.LevelUpCommandBuilder;
-import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.LogUtils;
+import java.io.File;
 import org.bukkit.configuration.ConfigurationSection;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.io.File;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 public class CommandOnLevelUpConfig extends BukkitConfig {
 
     public static final String LEVEL_UP_COMMANDS = "level_up_commands";

+ 1 - 1
src/main/java/com/gmail/nossr50/config/experience/ExperienceConfig.java

@@ -290,7 +290,7 @@ public class ExperienceConfig extends BukkitConfig {
         return config.getDouble(
                 "Experience_Formula.Skill_Multiplier." + StringUtils.getCapitalized(
                         skill.toString()),
-                1);
+                1D);
     }
 
     /* Custom XP perk */

+ 1 - 1
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -710,7 +710,7 @@ public class McMMOPlayer implements Identified {
      */
     public void applyXpGain(PrimarySkillType primarySkillType, float xp, XPGainReason xpGainReason,
             XPGainSource xpGainSource) {
-        if (!mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, primarySkillType)) {
+        if (!Permissions.skillEnabled(player, primarySkillType)) {
             return;
         }
 

+ 2 - 5
src/main/java/com/gmail/nossr50/datatypes/skills/PrimarySkillType.java

@@ -5,16 +5,13 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.skills.SkillTools;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
+import java.util.Set;
 import org.bukkit.entity.Entity;
 import org.bukkit.entity.Player;
 import org.jetbrains.annotations.NotNull;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
 public enum PrimarySkillType {
     ACROBATICS,
     ALCHEMY,

+ 5 - 5
src/main/java/com/gmail/nossr50/listeners/SelfListener.java

@@ -15,14 +15,13 @@ import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillTools;
 import com.gmail.nossr50.worldguard.WorldGuardManager;
 import com.gmail.nossr50.worldguard.WorldGuardUtils;
+import java.util.LinkedHashSet;
+import java.util.Set;
 import org.bukkit.entity.Player;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventPriority;
 import org.bukkit.event.Listener;
 
-import java.util.LinkedHashSet;
-import java.util.Set;
-
 public class SelfListener implements Listener {
     //Used in task scheduling and other things
     private final mcMMO plugin;
@@ -63,7 +62,7 @@ public class SelfListener implements Listener {
         final Set<Integer> levelsAchieved = new LinkedHashSet<>();
         final Set<Integer> powerLevelsAchieved = new LinkedHashSet<>();
         int startingLevel = event.getSkillLevel() - event.getLevelsGained();
-        int startingPowerLevel = mcMMOPlayer.getPowerLevel() - event.getLevelsGained();
+        int startingPowerLevel = mmoPlayer.getPowerLevel() - event.getLevelsGained();
         for (int i = 0; i < event.getLevelsGained(); i++) {
             levelsAchieved.add(startingLevel + (i + 1));
         }
@@ -71,7 +70,8 @@ public class SelfListener implements Listener {
             powerLevelsAchieved.add(startingPowerLevel + (i + 1));
         }
 
-        plugin.getLevelUpCommandManager().applySkillLevelUp(mcMMOPlayer, skill, levelsAchieved, powerLevelsAchieved);
+        plugin.getLevelUpCommandManager()
+                .applySkillLevelUp(mmoPlayer, skill, levelsAchieved, powerLevelsAchieved);
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

+ 1 - 2
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -4,6 +4,7 @@ import com.gmail.nossr50.chat.ChatManager;
 import com.gmail.nossr50.commands.CommandManager;
 import com.gmail.nossr50.commands.levelup.LevelUpCommandManager;
 import com.gmail.nossr50.config.AdvancedConfig;
+import com.gmail.nossr50.config.CommandOnLevelUpConfig;
 import com.gmail.nossr50.config.CoreSkillsConfig;
 import com.gmail.nossr50.config.CustomItemSupportConfig;
 import com.gmail.nossr50.config.GeneralConfig;
@@ -87,10 +88,8 @@ import org.bukkit.Bukkit;
 import org.bukkit.entity.Player;
 import org.bukkit.event.HandlerList;
 import org.bukkit.metadata.FixedMetadataValue;
-import org.bukkit.plugin.PluginDescriptionFile;
 import org.bukkit.plugin.PluginManager;
 import org.bukkit.plugin.java.JavaPlugin;
-import org.bukkit.plugin.java.JavaPluginLoader;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 

+ 16 - 14
src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java

@@ -27,6 +27,7 @@ import com.gmail.nossr50.util.skills.CombatUtils;
 import com.gmail.nossr50.util.skills.RankUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -209,18 +210,18 @@ public class WoodcuttingManager extends SkillManager {
      */
     @VisibleForTesting
     void processTree(Block block, Set<Block> treeFellerBlocks) {
-        List<Block> futureCenterBlocks = new ArrayList<>();
+        Collection<Block> futureCenterBlocks = new ArrayList<>();
 
         // Check the block up and take different behavior (smaller search) if it's a log
         if (processTreeFellerTargetBlock(block.getRelative(BlockFace.UP), futureCenterBlocks,
                 treeFellerBlocks)) {
             for (int[] dir : directions) {
-                processTreeFellerTargetBlock(block.getRelative(dir[0], 0, dir[1]),
-                        futureCenterBlocks, treeFellerBlocks);
-
                 if (treeFellerReachedThreshold) {
                     return;
                 }
+
+                processTreeFellerTargetBlock(block.getRelative(dir[0], 0, dir[1]),
+                        futureCenterBlocks, treeFellerBlocks);
             }
         } else {
             // Cover DOWN
@@ -229,12 +230,12 @@ public class WoodcuttingManager extends SkillManager {
             // Search in a cube
             for (int y = -1; y <= 1; y++) {
                 for (int[] dir : directions) {
-                    processTreeFellerTargetBlock(block.getRelative(dir[0], y, dir[1]),
-                            futureCenterBlocks, treeFellerBlocks);
-
                     if (treeFellerReachedThreshold) {
                         return;
                     }
+
+                    processTreeFellerTargetBlock(block.getRelative(dir[0], y, dir[1]),
+                            futureCenterBlocks, treeFellerBlocks);
                 }
             }
         }
@@ -302,23 +303,24 @@ public class WoodcuttingManager extends SkillManager {
      * @return true if and only if the given block was a Log not already in treeFellerBlocks.
      */
     private boolean processTreeFellerTargetBlock(@NotNull Block block,
-            @NotNull List<Block> futureCenterBlocks,
-            @NotNull Set<Block> treeFellerBlocks) {
+            @NotNull Collection<Block> futureCenterBlocks,
+            @NotNull Collection<Block> treeFellerBlocks) {
         if (treeFellerBlocks.contains(block) || mcMMO.getUserBlockTracker().isIneligible(block)) {
             return false;
         }
 
-        // Without this check Tree Feller propagates through leaves until the threshold is hit
-        if (treeFellerBlocks.size() > treeFellerThreshold) {
-            treeFellerReachedThreshold = true;
-        }
-
         if (BlockUtils.hasWoodcuttingXP(block)) {
             treeFellerBlocks.add(block);
             futureCenterBlocks.add(block);
+            if (treeFellerBlocks.size() >= treeFellerThreshold) {
+                treeFellerReachedThreshold = true;
+            }
             return true;
         } else if (BlockUtils.isNonWoodPartOfTree(block)) {
             treeFellerBlocks.add(block);
+            if (treeFellerBlocks.size() >= treeFellerThreshold) {
+                treeFellerReachedThreshold = true;
+            }
             return false;
         }
         return false;

+ 1 - 0
src/main/java/com/gmail/nossr50/util/skills/SkillTools.java

@@ -14,6 +14,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.HashSet;

+ 96 - 61
src/test/java/com/gmail/nossr50/MMOTestEnvironment.java

@@ -1,19 +1,23 @@
 package com.gmail.nossr50;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import com.gmail.nossr50.api.exceptions.InvalidSkillException;
+import com.gmail.nossr50.commands.levelup.LevelUpCommandManager;
 import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.ChatConfig;
+import com.gmail.nossr50.config.CommandOnLevelUpConfig;
 import com.gmail.nossr50.config.GeneralConfig;
 import com.gmail.nossr50.config.RankConfig;
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.config.party.PartyConfig;
+import com.gmail.nossr50.datatypes.experience.FormulaType;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.player.PlayerProfile;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@@ -22,9 +26,11 @@ import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.MaterialMapStore;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.TestPlayerMock;
 import com.gmail.nossr50.util.TransientEntityTracker;
 import com.gmail.nossr50.util.blockmeta.ChunkManager;
 import com.gmail.nossr50.util.compat.CompatibilityManager;
+import com.gmail.nossr50.util.experience.FormulaManager;
 import com.gmail.nossr50.util.platform.MinecraftGameVersion;
 import com.gmail.nossr50.util.player.NotificationManager;
 import com.gmail.nossr50.util.player.UserManager;
@@ -41,19 +47,17 @@ import org.bukkit.World;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
 import org.bukkit.entity.Player;
-import org.bukkit.event.Event;
 import org.bukkit.inventory.ItemFactory;
-import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.PlayerInventory;
 import org.bukkit.plugin.PluginManager;
 import org.mockito.MockedStatic;
-import org.mockito.Mockito;
 
 public abstract class MMOTestEnvironment {
     protected MockedStatic<Bukkit> mockedBukkit;
     protected MockedStatic<mcMMO> mockedMcMMO;
     protected MockedStatic<ChatConfig> mockedChatConfig;
     protected MockedStatic<ExperienceConfig> experienceConfig;
+    protected ExperienceConfig experienceConfigInstance;
     protected MockedStatic<Permissions> mockedPermissions;
     protected MockedStatic<RankUtils> mockedRankUtils;
     protected MockedStatic<UserManager> mockedUserManager;
@@ -63,6 +67,8 @@ public abstract class MMOTestEnvironment {
     protected MockedStatic<SoundManager> mockedSoundManager;
     protected TransientEntityTracker transientEntityTracker;
     protected AdvancedConfig advancedConfig;
+    protected CommandOnLevelUpConfig commandOnLevelUpConfig;
+    protected LevelUpCommandManager levelUpCommandManager;
     protected PartyConfig partyConfig;
     protected GeneralConfig generalConfig;
     protected RankConfig rankConfig;
@@ -70,21 +76,10 @@ public abstract class MMOTestEnvironment {
     protected Server server;
     protected PluginManager pluginManager;
     protected World world;
-
-    /* Mocks */
-    protected Player player;
-
-    protected UUID playerUUID = UUID.randomUUID();
-    protected ItemStack itemInMainHand;
-
-    protected PlayerInventory playerInventory;
-    protected PlayerProfile playerProfile;
-    protected McMMOPlayer mmoPlayer;
+    private FormulaManager formulaManager;
     protected ItemFactory itemFactory;
-
     protected ChunkManager chunkManager;
     protected MaterialMapStore materialMapStore;
-
     protected CompatibilityManager compatibilityManager;
 
     protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException {
@@ -98,6 +93,10 @@ public abstract class MMOTestEnvironment {
         mcMMO.p = mock(mcMMO.class);
         when(mcMMO.p.getLogger()).thenReturn(logger);
 
+        // formula manager
+        formulaManager = new FormulaManager(FormulaType.UNKNOWN);
+        when(mcMMO.p.getFormulaManager()).thenReturn(formulaManager);
+
         // place store
         chunkManager = mock(ChunkManager.class);
         when(mcMMO.getUserBlockTracker()).thenReturn(chunkManager);
@@ -118,6 +117,9 @@ public abstract class MMOTestEnvironment {
         // wire advanced config
         mockAdvancedConfig();
 
+        // wire command level up config
+        mockLevelUpCommand();
+
         // wire experience config
         mockExperienceConfig();
 
@@ -128,8 +130,6 @@ public abstract class MMOTestEnvironment {
         this.transientEntityTracker = new TransientEntityTracker();
         when(mcMMO.getTransientEntityTracker()).thenReturn(transientEntityTracker);
 
-        mockPermissions();
-
         mockedRankUtils = mockStatic(RankUtils.class);
 
         // wire server
@@ -150,11 +150,6 @@ public abstract class MMOTestEnvironment {
         when(server.getPluginManager()).thenReturn(pluginManager);
         // wire Bukkit -> plugin manager
         when(Bukkit.getPluginManager()).thenReturn(pluginManager);
-        // return the argument provided when call event is invoked on plugin manager mock
-        doAnswer(invocation -> {
-            Object[] args = invocation.getArguments();
-            return args[0];
-        }).when(pluginManager).callEvent(any(Event.class));
 
         // wire world
         this.world = mock(World.class);
@@ -164,30 +159,8 @@ public abstract class MMOTestEnvironment {
         when(Misc.getBlockCenter(any(Block.class))).thenReturn(new Location(world, 0, 0, 0));
         when(Misc.getBlockCenter(any(BlockState.class))).thenReturn(new Location(world, 0, 0, 0));
 
-        // setup player and player related mocks after everything else
-        this.player = mock(Player.class);
-        when(player.getUniqueId()).thenReturn(playerUUID);
-        when(player.isValid()).thenReturn(true);
-        when(player.isOnline()).thenReturn(true);
-        // health
-        when(player.getHealth()).thenReturn(20D);
-        // wire inventory
-        this.playerInventory = mock(PlayerInventory.class);
-        when(player.getInventory()).thenReturn(playerInventory);
-        // player location
-        Location playerLocation = mock(Location.class);
-        Block playerLocationBlock = mock(Block.class);
-        when(player.getLocation()).thenReturn(playerLocation);
-        when(playerLocation.getBlock()).thenReturn(playerLocationBlock);
-        // when(playerLocationBlock.getType()).thenReturn(Material.AIR);
-
-        // PlayerProfile and McMMOPlayer are partially mocked
-        playerProfile = new PlayerProfile("testPlayer", player.getUniqueId(), 0);
-        mmoPlayer = Mockito.spy(new McMMOPlayer(player, playerProfile));
-
         // wire user manager
         this.mockedUserManager = mockStatic(UserManager.class);
-        when(UserManager.getPlayer(player)).thenReturn(mmoPlayer);
 
         this.materialMapStore = new MaterialMapStore();
         when(mcMMO.getMaterialMapStore()).thenReturn(materialMapStore);
@@ -199,18 +172,15 @@ public abstract class MMOTestEnvironment {
         mockedSoundManager = mockStatic(SoundManager.class);
     }
 
-    private void mockPermissions() {
-        mockedPermissions = mockStatic(Permissions.class);
-        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.canUseSubSkill(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.canUseSubSkill(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.lucky(player, PrimarySkillType.WOODCUTTING)).thenReturn(
-                false); // player is not lucky
+    private void mockPermissions(Player player) {
+        if (mockedPermissions == null) {
+            mockedPermissions = mockStatic(Permissions.class);
+        }
+        when(Permissions.isSubSkillEnabled(eq(player), any(SubSkillType.class))).thenReturn(true);
+        when(Permissions.canUseSubSkill(eq(player), any(SubSkillType.class))).thenReturn(true);
+        when(Permissions.isSubSkillEnabled(eq(player), any(SubSkillType.class))).thenReturn(true);
+        when(Permissions.canUseSubSkill(eq(player), any(SubSkillType.class))).thenReturn(true);
+        when(Permissions.skillEnabled(eq(player), any(PrimarySkillType.class))).thenReturn(true);
     }
 
     private void mockRankConfig() {
@@ -222,13 +192,26 @@ public abstract class MMOTestEnvironment {
         when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
     }
 
+    private void mockLevelUpCommand() {
+        this.commandOnLevelUpConfig = mock(CommandOnLevelUpConfig.class);
+        when(mcMMO.p.getCommandOnLevelUpConfig()).thenReturn(commandOnLevelUpConfig);
+
+        this.levelUpCommandManager = spy(new LevelUpCommandManager(mcMMO.p));
+        when(mcMMO.p.getLevelUpCommandManager()).thenReturn(levelUpCommandManager);
+    }
+
     private void mockGeneralConfig() {
         generalConfig = mock(GeneralConfig.class);
+        when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
         when(generalConfig.getTreeFellerThreshold()).thenReturn(100);
         when(generalConfig.getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING,
                 Material.OAK_LOG)).thenReturn(true);
         when(generalConfig.getLocale()).thenReturn("en_US");
-        when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
+        // Allows pseudo functional testing of experience gains
+        when(generalConfig.getPowerLevelCap())
+                .thenReturn(Integer.MAX_VALUE);
+        when(generalConfig.getLevelCap(any(PrimarySkillType.class)))
+                .thenReturn(Integer.MAX_VALUE);
     }
 
     private void mockPartyConfig() {
@@ -239,11 +222,63 @@ public abstract class MMOTestEnvironment {
 
     private void mockExperienceConfig() {
         experienceConfig = mockStatic(ExperienceConfig.class);
+        experienceConfigInstance = mock(ExperienceConfig.class);
+        when(ExperienceConfig.getInstance()).thenReturn(experienceConfigInstance);
+        when(experienceConfigInstance.getFormulaType()).thenReturn(FormulaType.LINEAR);
+        when(experienceConfigInstance.getFormulaSkillModifier(any(PrimarySkillType.class)))
+                .thenReturn(1D);
+        when(experienceConfigInstance.getBase(any(FormulaType.class)))
+                .thenReturn(1000);
+        when(experienceConfigInstance.getExponent(any())).thenReturn(1D);
+        when(experienceConfigInstance.getExperienceGainsGlobalMultiplier())
+                .thenReturn(1D);
+        when(experienceConfigInstance.getMultiplier(any(FormulaType.class)))
+                .thenReturn(1D);
+        // Conversion
+        when(experienceConfigInstance.getExpModifier())
+                .thenReturn(1D);
+    }
+
+    protected TestPlayerMock mockPlayer() {
+        final UUID uuid = UUID.randomUUID();
+        return mockPlayer(uuid, uuid.toString(), 0);
+    }
+
+    protected TestPlayerMock mockPlayer(UUID uuid, String playerName, int startingLevel) {
+        final Player player = mock(Player.class);
+        when(player.getUniqueId()).thenReturn(uuid);
+        when(player.isValid()).thenReturn(true);
+        when(player.isOnline()).thenReturn(true);
+        // Player name
+        when(player.getName()).thenReturn(playerName);
+        // health
+        when(player.getHealth()).thenReturn(20D);
 
-        when(ExperienceConfig.getInstance()).thenReturn(mock(ExperienceConfig.class));
+        // inventory
+        final PlayerInventory playerInventory = mock(PlayerInventory.class);
+        when(player.getInventory()).thenReturn(playerInventory);
+
+        // player location
+        final Location playerLocation = mock(Location.class);
+        final Block playerLocationBlock = mock(Block.class);
+        when(player.getLocation()).thenReturn(playerLocation);
+        when(playerLocation.getBlock()).thenReturn(playerLocationBlock);
+
+        // PlayerProfile and McMMOPlayer are partially mocked
+        final PlayerProfile playerProfile = spy(new PlayerProfile("testPlayer", player.getUniqueId(),
+                startingLevel));
+        when(playerProfile.isLoaded()).thenReturn(true);
+        final McMMOPlayer mmoPlayer = spy(new McMMOPlayer(player, playerProfile));
+        when(UserManager.getPlayer(player)).thenReturn(mmoPlayer);
+
+        // Permissions
+        mockPermissions(player);
+        // TODO: Move this to the woodcutting tests
+        when(Permissions.lucky(player, PrimarySkillType.WOODCUTTING)).thenReturn(
+                false); // player is not lucky
 
-        // Combat
-        when(ExperienceConfig.getInstance().getCombatXP("Cow")).thenReturn(1D);
+        return new TestPlayerMock(player, playerInventory, playerLocation, playerProfile,
+                mmoPlayer);
     }
 
     protected void cleanUpStaticMocks() {

+ 268 - 295
src/test/java/com/gmail/nossr50/MMOTestEnvironmentBasic.java

@@ -1,295 +1,268 @@
-package com.gmail.nossr50;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.gmail.nossr50.commands.levelup.LevelUpCommandManager;
-import com.gmail.nossr50.config.AdvancedConfig;
-import com.gmail.nossr50.config.ChatConfig;
-import com.gmail.nossr50.config.CommandOnLevelUpConfig;
-import com.gmail.nossr50.config.GeneralConfig;
-import com.gmail.nossr50.config.RankConfig;
-import com.gmail.nossr50.config.experience.ExperienceConfig;
-import com.gmail.nossr50.datatypes.experience.FormulaType;
-import com.gmail.nossr50.datatypes.player.McMMOPlayer;
-import com.gmail.nossr50.datatypes.player.PlayerProfile;
-import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
-import com.gmail.nossr50.datatypes.skills.SubSkillType;
-import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
-import com.gmail.nossr50.events.experience.McMMOPlayerPreXpGainEvent;
-import com.gmail.nossr50.listeners.SelfListener;
-import com.gmail.nossr50.util.EventUtils;
-import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.TransientEntityTracker;
-import com.gmail.nossr50.util.blockmeta.ChunkManager;
-import com.gmail.nossr50.util.experience.FormulaManager;
-import com.gmail.nossr50.util.player.NotificationManager;
-import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.RankUtils;
-import com.gmail.nossr50.util.skills.SkillTools;
-import java.util.UUID;
-import org.bukkit.Bukkit;
-import org.bukkit.Server;
-import org.bukkit.World;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.PlayerInventory;
-import org.bukkit.plugin.PluginManager;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
-
-public abstract class MMOTestEnvironmentBasic {
-    private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(
-            MMOTestEnvironmentBasic.class.getName());
-    protected MockedStatic<mcMMO> mockedMcMMO;
-    protected MockedStatic<Bukkit> mockedBukkit;
-    protected MockedStatic<ChatConfig> mockedChatConfig;
-    protected MockedStatic<ExperienceConfig> experienceConfig;
-    private MockedStatic<NotificationManager> mockedNotificationManager;
-    protected MockedStatic<Permissions> mockedPermissions;
-    protected MockedStatic<RankUtils> mockedRankUtils;
-    protected MockedStatic<UserManager> mockedUserManager;
-    protected MockedStatic<Misc> mockedMisc;
-    protected MockedStatic<EventUtils> mockedEventUtils;
-    protected SelfListener selfListener;
-    protected TransientEntityTracker transientEntityTracker;
-    protected AdvancedConfig advancedConfig;
-    protected CommandOnLevelUpConfig commandOnLevelUpConfig;
-    protected LevelUpCommandManager levelUpCommandManager;
-    protected GeneralConfig generalConfig;
-    protected RankConfig rankConfig;
-    protected SkillTools skillTools;
-    protected Server mockedServer;
-    protected PluginManager pluginManager;
-    protected World world;
-
-    private FormulaManager formulaManager;
-
-    /* Mocks */
-    protected PlayerInventory playerInventory;
-
-    protected ChunkManager chunkManager;
-
-    protected ConsoleCommandSender consoleCommandSender;
-
-    @BeforeEach
-    void setUp() {
-        mockBaseEnvironment();
-    }
-
-    @AfterEach
-    void tearDown() {
-        cleanupBaseEnvironment();
-    }
-
-    protected void mockBaseEnvironment() {
-        mockedMcMMO = Mockito.mockStatic(mcMMO.class);
-        mcMMO.p = mock(mcMMO.class);
-        when(mcMMO.p.getLogger()).thenReturn(logger);
-
-        // formula manager
-        formulaManager = new FormulaManager(FormulaType.UNKNOWN);
-        when(mcMMO.p.getFormulaManager()).thenReturn(formulaManager);
-
-        // place store
-        chunkManager = mock(ChunkManager.class);
-        when(mcMMO.getPlaceStore()).thenReturn(chunkManager);
-
-        // shut off mod manager for woodcutting
-        when(mcMMO.getModManager()).thenReturn(mock(ModManager.class));
-        when(mcMMO.getModManager().isCustomLog(any())).thenReturn(false);
-
-        // chat config
-        mockedChatConfig = Mockito.mockStatic(ChatConfig.class);
-        when(ChatConfig.getInstance()).thenReturn(mock(ChatConfig.class));
-
-        // general config
-        mockGeneralConfig();
-
-        // rank config
-        mockRankConfig();
-
-        // wire advanced config
-        mockAdvancedConfig();
-
-        // wire command level up config
-        mockLevelUpCommand();
-
-        // wire experience config
-        mockExperienceConfig();
-
-        // wire skill tools
-        this.skillTools = Mockito.spy(new SkillTools(mcMMO.p));
-        when(mcMMO.p.getSkillTools()).thenReturn(skillTools);
-
-        this.transientEntityTracker = new TransientEntityTracker();
-        when(mcMMO.getTransientEntityTracker()).thenReturn(transientEntityTracker);
-
-        mockPermissions();
-
-        mockNotifications();
-
-        mockedRankUtils = Mockito.mockStatic(RankUtils.class);
-
-        // wire server
-        this.mockedServer = mock(Server.class);
-        when(mcMMO.p.getServer()).thenReturn(mockedServer);
-
-        // wire plugin manager
-        this.pluginManager = mock(PluginManager.class);
-        when(mockedServer.getPluginManager()).thenReturn(pluginManager);
-        // Process level up events in our self listener
-        Mockito.doAnswer(invocation -> {
-            selfListener.onPlayerLevelUp(invocation.getArgument(0));
-            return null;
-        }).when(pluginManager).callEvent(any(McMMOPlayerLevelUpEvent.class));
-
-        // Don't process pre-gain events
-        Mockito.doAnswer((ignored) -> null).when(pluginManager)
-                .callEvent(any(McMMOPlayerPreXpGainEvent.class));
-
-        // wire world
-        this.world = mock(World.class);
-
-        // wire Misc
-        this.mockedMisc = Mockito.mockStatic(Misc.class);
-        // Mockito.when(Misc.getBlockCenter(any())).thenReturn(new Location(world, 0, 0, 0));
-
-        // wire user manager
-        this.mockedUserManager = Mockito.mockStatic(UserManager.class);
-
-        // Self listener
-        selfListener = Mockito.spy(new SelfListener(mcMMO.p));
-
-        // Console command sender
-        consoleCommandSender = mock(ConsoleCommandSender.class);
-        when(consoleCommandSender.getName()).thenReturn("CONSOLE");
-        mockedBukkit = Mockito.mockStatic(Bukkit.class);
-        when(Bukkit.getConsoleSender()).thenReturn(consoleCommandSender);
-    }
-
-    private void mockPermissions() {
-        mockedPermissions = Mockito.mockStatic(Permissions.class);
-        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
-                true);
-        when(Permissions.skillEnabled(any(Player.class), any(PrimarySkillType.class))).thenReturn(
-                true);
-    }
-
-    private void mockNotifications() {
-        mockedNotificationManager = Mockito.mockStatic(NotificationManager.class);
-    }
-
-    private void mockRankConfig() {
-        rankConfig = mock(RankConfig.class);
-    }
-
-    private void mockAdvancedConfig() {
-        this.advancedConfig = mock(AdvancedConfig.class);
-        when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
-    }
-
-    private void mockLevelUpCommand() {
-        this.commandOnLevelUpConfig = mock(CommandOnLevelUpConfig.class);
-        when(mcMMO.p.getCommandOnLevelUpConfig()).thenReturn(commandOnLevelUpConfig);
-
-        this.levelUpCommandManager = Mockito.spy(new LevelUpCommandManager(mcMMO.p));
-        when(mcMMO.p.getLevelUpCommandManager()).thenReturn(levelUpCommandManager);
-    }
-
-    private void mockGeneralConfig() {
-        generalConfig = mock(GeneralConfig.class);
-        when(generalConfig.getLocale()).thenReturn("en_US");
-        when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
-
-        // Experience related
-        when(generalConfig.getLevelCap(any(PrimarySkillType.class))).thenReturn(Integer.MAX_VALUE);
-        when(generalConfig.getPowerLevelCap()).thenReturn(Integer.MAX_VALUE);
-    }
-
-    private void mockExperienceConfig() {
-        experienceConfig = Mockito.mockStatic(ExperienceConfig.class);
-
-        when(ExperienceConfig.getInstance()).thenReturn(mock(ExperienceConfig.class));
-
-        // Combat
-        when(ExperienceConfig.getInstance().getCombatXP(EntityType.COW)).thenReturn(1D);
-        when(ExperienceConfig.getInstance().getFormulaType()).thenReturn(FormulaType.LINEAR);
-        when(ExperienceConfig.getInstance().getBase(FormulaType.LINEAR)).thenReturn(1020);
-        when(ExperienceConfig.getInstance().getMultiplier(FormulaType.LINEAR)).thenReturn(20D);
-        when(ExperienceConfig.getInstance()
-                .getFormulaSkillModifier(any(PrimarySkillType.class))).thenReturn(1D);
-        when(ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier()).thenReturn(1D);
-        when(ExperienceConfig.getInstance().getExpModifier()).thenReturn(1D);
-    }
-
-    protected void cleanupBaseEnvironment() {
-        // Clean up resources here if needed.
-        if (mockedMcMMO != null) {
-            mockedMcMMO.close();
-        }
-        if (mockedBukkit != null) {
-            mockedBukkit.close();
-        }
-        if (experienceConfig != null) {
-            experienceConfig.close();
-        }
-        if (mockedChatConfig != null) {
-            mockedChatConfig.close();
-        }
-        if (mockedPermissions != null) {
-            mockedPermissions.close();
-        }
-        if (mockedRankUtils != null) {
-            mockedRankUtils.close();
-        }
-        if (mockedUserManager != null) {
-            mockedUserManager.close();
-        }
-        if (mockedMisc != null) {
-            mockedMisc.close();
-        }
-        if (mockedEventUtils != null) {
-            mockedEventUtils.close();
-        }
-        if (mockedNotificationManager != null) {
-            mockedNotificationManager.close();
-        }
-    }
-
-    protected McMMOPlayer getMMOPlayer(UUID playerUUID, String playerName, int startingLevel) {
-        Player player = mock(Player.class);
-        // Player UUID
-        when(player.getUniqueId()).thenReturn(playerUUID);
-        // Player name
-        when(player.getName()).thenReturn(playerName);
-
-        // Player Inventory
-        this.playerInventory = mock(PlayerInventory.class);
-        when(player.getInventory()).thenReturn(playerInventory);
-
-        // Player Profile
-        PlayerProfile playerProfile = Mockito.spy(
-                new PlayerProfile(playerName, player.getUniqueId(), startingLevel));
-        when(playerProfile.isLoaded()).thenReturn(true);
-        // McMMOPlayer
-        McMMOPlayer mmoPlayer = Mockito.spy(new McMMOPlayer(player, playerProfile));
-        // Wire UserManager
-        when(UserManager.getPlayer(player)).thenReturn(mmoPlayer);
-        // Player is online
-        when(player.isOnline()).thenReturn(true);
-
-        return mmoPlayer;
-    }
-
-    protected McMMOPlayer getMMOPlayer(UUID playerUUID, String playerName) {
-        return getMMOPlayer(playerUUID, playerName, 0);
-    }
-}
+//package com.gmail.nossr50;
+//
+//import static org.mockito.ArgumentMatchers.any;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.when;
+//
+//import com.gmail.nossr50.commands.levelup.LevelUpCommandManager;
+//import com.gmail.nossr50.config.AdvancedConfig;
+//import com.gmail.nossr50.config.ChatConfig;
+//import com.gmail.nossr50.config.CommandOnLevelUpConfig;
+//import com.gmail.nossr50.config.GeneralConfig;
+//import com.gmail.nossr50.config.RankConfig;
+//import com.gmail.nossr50.config.experience.ExperienceConfig;
+//import com.gmail.nossr50.datatypes.experience.FormulaType;
+//import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+//import com.gmail.nossr50.datatypes.player.PlayerProfile;
+//import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
+//import com.gmail.nossr50.datatypes.skills.SubSkillType;
+//import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
+//import com.gmail.nossr50.events.experience.McMMOPlayerPreXpGainEvent;
+//import com.gmail.nossr50.listeners.SelfListener;
+//import com.gmail.nossr50.util.EventUtils;
+//import com.gmail.nossr50.util.Misc;
+//import com.gmail.nossr50.util.Permissions;
+//import com.gmail.nossr50.util.TransientEntityTracker;
+//import com.gmail.nossr50.util.blockmeta.ChunkManager;
+//import com.gmail.nossr50.util.experience.FormulaManager;
+//import com.gmail.nossr50.util.player.NotificationManager;
+//import com.gmail.nossr50.util.player.UserManager;
+//import com.gmail.nossr50.util.skills.RankUtils;
+//import com.gmail.nossr50.util.skills.SkillTools;
+//import java.util.UUID;
+//import org.bukkit.Bukkit;
+//import org.bukkit.Server;
+//import org.bukkit.World;
+//import org.bukkit.command.ConsoleCommandSender;
+//import org.bukkit.entity.EntityType;
+//import org.bukkit.entity.Player;
+//import org.bukkit.inventory.PlayerInventory;
+//import org.bukkit.plugin.PluginManager;
+//import org.junit.jupiter.api.AfterEach;
+//import org.junit.jupiter.api.BeforeEach;
+//import org.mockito.MockedStatic;
+//import org.mockito.Mockito;
+//
+//public abstract class MMOTestEnvironmentBasic {
+//    private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(
+//            MMOTestEnvironmentBasic.class.getName());
+//    protected MockedStatic<mcMMO> mockedMcMMO;
+//    protected MockedStatic<Bukkit> mockedBukkit;
+//    protected MockedStatic<ChatConfig> mockedChatConfig;
+//    protected MockedStatic<ExperienceConfig> experienceConfig;
+//    private MockedStatic<NotificationManager> mockedNotificationManager;
+//    protected MockedStatic<Permissions> mockedPermissions;
+//    protected MockedStatic<RankUtils> mockedRankUtils;
+//    protected MockedStatic<UserManager> mockedUserManager;
+//    protected MockedStatic<Misc> mockedMisc;
+//    protected MockedStatic<EventUtils> mockedEventUtils;
+//    protected SelfListener selfListener;
+//    protected TransientEntityTracker transientEntityTracker;
+//    protected AdvancedConfig advancedConfig;
+//    protected CommandOnLevelUpConfig commandOnLevelUpConfig;
+//    protected LevelUpCommandManager levelUpCommandManager;
+//    protected GeneralConfig generalConfig;
+//    protected RankConfig rankConfig;
+//    protected SkillTools skillTools;
+//    protected Server mockedServer;
+//    protected PluginManager pluginManager;
+//    protected World world;
+//
+//    private FormulaManager formulaManager;
+//
+//    /* Mocks */
+//    protected PlayerInventory playerInventory;
+//
+//    protected ChunkManager chunkManager;
+//
+//    protected ConsoleCommandSender consoleCommandSender;
+//
+//    @BeforeEach
+//    void setUp() {
+//        mockBaseEnvironment();
+//    }
+//
+//    @AfterEach
+//    void tearDown() {
+//        cleanupBaseEnvironment();
+//    }
+//
+//    protected void mockBaseEnvironment() {
+//        mockedMcMMO = Mockito.mockStatic(mcMMO.class);
+//        mcMMO.p = mock(mcMMO.class);
+//        when(mcMMO.p.getLogger()).thenReturn(logger);
+//
+//        // formula manager
+//        formulaManager = new FormulaManager(FormulaType.UNKNOWN);
+//        when(mcMMO.p.getFormulaManager()).thenReturn(formulaManager);
+//
+//        // place store
+//        chunkManager = mock(ChunkManager.class);
+//        when(mcMMO.getPlaceStore()).thenReturn(chunkManager);
+//
+//        // shut off mod manager for woodcutting
+//        when(mcMMO.getModManager()).thenReturn(mock(ModManager.class));
+//        when(mcMMO.getModManager().isCustomLog(any())).thenReturn(false);
+//
+//        // chat config
+//        mockedChatConfig = Mockito.mockStatic(ChatConfig.class);
+//        when(ChatConfig.getInstance()).thenReturn(mock(ChatConfig.class));
+//
+//        // general config
+//        mockGeneralConfig();
+//
+//        // rank config
+//        mockRankConfig();
+//
+//        // wire advanced config
+//        mockAdvancedConfig();
+//
+//        // wire command level up config
+//        mockLevelUpCommand();
+//
+//        // wire experience config
+//        mockExperienceConfig();
+//
+//        // wire skill tools
+//        this.skillTools = Mockito.spy(new SkillTools(mcMMO.p));
+//        when(mcMMO.p.getSkillTools()).thenReturn(skillTools);
+//
+//        this.transientEntityTracker = new TransientEntityTracker();
+//        when(mcMMO.getTransientEntityTracker()).thenReturn(transientEntityTracker);
+//
+//        mockPermissions();
+//
+//        mockNotifications();
+//
+//        mockedRankUtils = Mockito.mockStatic(RankUtils.class);
+//
+//        // wire server
+//        this.mockedServer = mock(Server.class);
+//        when(mcMMO.p.getServer()).thenReturn(mockedServer);
+//
+//        // wire plugin manager
+//        this.pluginManager = mock(PluginManager.class);
+//        when(mockedServer.getPluginManager()).thenReturn(pluginManager);
+//        // Process level up events in our self listener
+//        Mockito.doAnswer(invocation -> {
+//            selfListener.onPlayerLevelUp(invocation.getArgument(0));
+//            return null;
+//        }).when(pluginManager).callEvent(any(McMMOPlayerLevelUpEvent.class));
+//
+//        // Don't process pre-gain events
+//        Mockito.doAnswer((ignored) -> null).when(pluginManager)
+//                .callEvent(any(McMMOPlayerPreXpGainEvent.class));
+//
+//        // wire world
+//        this.world = mock(World.class);
+//
+//        // wire Misc
+//        this.mockedMisc = Mockito.mockStatic(Misc.class);
+//        // Mockito.when(Misc.getBlockCenter(any())).thenReturn(new Location(world, 0, 0, 0));
+//
+//        // wire user manager
+//        this.mockedUserManager = Mockito.mockStatic(UserManager.class);
+//
+//        // Self listener
+//        selfListener = Mockito.spy(new SelfListener(mcMMO.p));
+//
+//        // Console command sender
+//        consoleCommandSender = mock(ConsoleCommandSender.class);
+//        when(consoleCommandSender.getName()).thenReturn("CONSOLE");
+//        mockedBukkit = Mockito.mockStatic(Bukkit.class);
+//        when(Bukkit.getConsoleSender()).thenReturn(consoleCommandSender);
+//    }
+//
+//    private void mockPermissions() {
+//        mockedPermissions = Mockito.mockStatic(Permissions.class);
+//        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
+//                true);
+//        when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(
+//                true);
+//        when(Permissions.skillEnabled(any(Player.class), any(PrimarySkillType.class))).thenReturn(
+//                true);
+//    }
+//
+//    private void mockNotifications() {
+//        mockedNotificationManager = Mockito.mockStatic(NotificationManager.class);
+//    }
+//
+//    private void mockRankConfig() {
+//        rankConfig = mock(RankConfig.class);
+//    }
+//
+//    private void mockAdvancedConfig() {
+//        this.advancedConfig = mock(AdvancedConfig.class);
+//        when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
+//    }
+//
+//    private void mockLevelUpCommand() {
+//        this.commandOnLevelUpConfig = mock(CommandOnLevelUpConfig.class);
+//        when(mcMMO.p.getCommandOnLevelUpConfig()).thenReturn(commandOnLevelUpConfig);
+//
+//        this.levelUpCommandManager = Mockito.spy(new LevelUpCommandManager(mcMMO.p));
+//        when(mcMMO.p.getLevelUpCommandManager()).thenReturn(levelUpCommandManager);
+//    }
+//
+//    private void mockGeneralConfig() {
+//        generalConfig = mock(GeneralConfig.class);
+//        when(generalConfig.getLocale()).thenReturn("en_US");
+//        when(mcMMO.p.getGeneralConfig()).thenReturn(generalConfig);
+//
+//        // Experience related
+//        when(generalConfig.getLevelCap(any(PrimarySkillType.class))).thenReturn(Integer.MAX_VALUE);
+//        when(generalConfig.getPowerLevelCap()).thenReturn(Integer.MAX_VALUE);
+//    }
+//
+//    private void mockExperienceConfig() {
+//        experienceConfig = Mockito.mockStatic(ExperienceConfig.class);
+//
+//        when(ExperienceConfig.getInstance()).thenReturn(mock(ExperienceConfig.class));
+//
+//        // Combat
+//        when(ExperienceConfig.getInstance().getCombatXP(EntityType.COW)).thenReturn(1D);
+//        when(ExperienceConfig.getInstance().getFormulaType()).thenReturn(FormulaType.LINEAR);
+//        when(ExperienceConfig.getInstance().getBase(FormulaType.LINEAR)).thenReturn(1020);
+//        when(ExperienceConfig.getInstance().getMultiplier(FormulaType.LINEAR)).thenReturn(20D);
+//        when(ExperienceConfig.getInstance()
+//                .getFormulaSkillModifier(any(PrimarySkillType.class))).thenReturn(1D);
+//        when(ExperienceConfig.getInstance().getExperienceGainsGlobalMultiplier()).thenReturn(1D);
+//        when(ExperienceConfig.getInstance().getExpModifier()).thenReturn(1D);
+//    }
+//
+//    protected void cleanupBaseEnvironment() {
+//        // Clean up resources here if needed.
+//        if (mockedMcMMO != null) {
+//            mockedMcMMO.close();
+//        }
+//        if (mockedBukkit != null) {
+//            mockedBukkit.close();
+//        }
+//        if (experienceConfig != null) {
+//            experienceConfig.close();
+//        }
+//        if (mockedChatConfig != null) {
+//            mockedChatConfig.close();
+//        }
+//        if (mockedPermissions != null) {
+//            mockedPermissions.close();
+//        }
+//        if (mockedRankUtils != null) {
+//            mockedRankUtils.close();
+//        }
+//        if (mockedUserManager != null) {
+//            mockedUserManager.close();
+//        }
+//        if (mockedMisc != null) {
+//            mockedMisc.close();
+//        }
+//        if (mockedEventUtils != null) {
+//            mockedEventUtils.close();
+//        }
+//        if (mockedNotificationManager != null) {
+//            mockedNotificationManager.close();
+//        }
+//    }
+//
+//
+//}

+ 118 - 74
src/test/java/com/gmail/nossr50/commands/levelup/LevelUpCommandTest.java

@@ -3,6 +3,7 @@ package com.gmail.nossr50.commands.levelup;
 import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.MINING;
 import static com.gmail.nossr50.datatypes.skills.PrimarySkillType.WOODCUTTING;
 import static java.util.Objects.requireNonNull;
+import static java.util.logging.Logger.getLogger;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.atLeast;
@@ -12,41 +13,72 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import com.gmail.nossr50.MMOTestEnvironmentBasic;
+import com.gmail.nossr50.MMOTestEnvironment;
 import com.gmail.nossr50.datatypes.experience.XPGainReason;
 import com.gmail.nossr50.datatypes.experience.XPGainSource;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
+import com.gmail.nossr50.events.experience.McMMOPlayerPreXpGainEvent;
+import com.gmail.nossr50.events.experience.McMMOPlayerXpGainEvent;
+import com.gmail.nossr50.listeners.SelfListener;
 import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.EventUtils;
+import com.gmail.nossr50.util.TestPlayerMock;
 import java.util.List;
 import java.util.UUID;
 import java.util.function.BiPredicate;
 import java.util.function.Predicate;
+import java.util.logging.Logger;
 import org.bukkit.Bukkit;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 
-class LevelUpCommandTest extends MMOTestEnvironmentBasic {
+class LevelUpCommandTest extends MMOTestEnvironment {
+    private static final Logger logger = getLogger(LevelUpCommandTest.class.getName());
     private static final BiPredicate<PrimarySkillType, Integer> ALWAYS_TRUE = (skill, level) -> true;
-    private McMMOPlayer mmoPlayer;
-    private final String playerName = "Momshroom";
+    private static final String DEFAULT_PLAYER_NAME = "Momshroom";
+    private SelfListener selfListener;
 
     @BeforeEach
     void beforeEach() {
+        mockBaseEnvironment(logger);
         mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().clear();
 
-        this.mmoPlayer = getMMOPlayer(UUID.randomUUID(), playerName, 0);
+        // Self listener
+        selfListener = Mockito.spy(new SelfListener(mcMMO.p));
+
+        // Process level up events in our self listener
+        Mockito.doAnswer(invocation -> {
+            selfListener.onPlayerLevelUp(invocation.getArgument(0));
+            return null;
+        }).when(pluginManager).callEvent(any(McMMOPlayerLevelUpEvent.class));
+
+        Mockito.doAnswer(invocation -> {
+            selfListener.onPlayerXpGain(invocation.getArgument(0));
+            return null;
+        }).when(pluginManager).callEvent(any(McMMOPlayerXpGainEvent.class));
+
+        Mockito.doAnswer(invocation -> {
+            return invocation.getArgument(0);
+        }).when(pluginManager).callEvent(any(McMMOPlayerPreXpGainEvent.class));
+
+
+    }
+
+    @AfterEach
+    void tearDown() {
+        cleanUpStaticMocks();
     }
 
     @Test
     void skillLevelUpShouldRunFiveTimes() {
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
         final String commandStr = "say hello";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
@@ -65,37 +97,39 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
         mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(5));
     }
 
-    @Test
-    void dualRequirementsShouldRunOnce() {
-        // GIVEN
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
-        final String commandStr = "say hello";
-        BiPredicate<PrimarySkillType, Integer> predicate = (skill, skillLevel) -> skill == MINING
-                && skillLevel == 3;
-        BiPredicate<PrimarySkillType, Integer> predicate2 = (skill, skillLevel) ->
-                skill == WOODCUTTING && skillLevel == 3;
-        final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
-                List.of(predicate, predicate2));
-
-        mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
-
-        // WHEN player gains 5 levels in mining and woodcutting via command
-        levelPlayerViaXP(mmoPlayer, MINING, 5);
-        levelPlayerViaXP(mmoPlayer, WOODCUTTING, 5);
-
-        // THEN the command should be checked for execution
-        verify(levelUpCommandManager, atLeastOnce()).applySkillLevelUp(any(), any(), any(), any());
-        verify(levelUpCommand, times(10)).process(any(), any(), any(), any());
-
-        // THEN the command should have executed
-        verify(levelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class));
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(1));
-    }
+//    @Test
+//    void dualRequirementsShouldRunOnce() {
+//        // GIVEN
+//        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+//        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+//        final String commandStr = "say hello";
+//        BiPredicate<PrimarySkillType, Integer> predicate = (skill, skillLevel) -> skill == MINING
+//                && skillLevel == 3;
+//        BiPredicate<PrimarySkillType, Integer> predicate2 = (skill, skillLevel) ->
+//                skill == WOODCUTTING && skillLevel == 3;
+//        final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
+//                List.of(predicate, predicate2));
+//
+//        mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
+//
+//        // WHEN player gains 5 levels in mining and woodcutting via command
+//        levelPlayerViaXP(mmoPlayer, MINING, 5);
+//        levelPlayerViaXP(mmoPlayer, WOODCUTTING, 5);
+//
+//        // THEN the command should be checked for execution
+//        verify(levelUpCommandManager, times(10)).applySkillLevelUp(any(), any(), any(), any());
+//        verify(levelUpCommand, times(10)).process(any(), any(), any(), any());
+//
+//        // THEN the command should have executed
+//        verify(levelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class));
+//        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), any()), atLeast(1));
+//    }
 
     @Test
     void skillLevelUpViaXPGainShouldRunFiveTimes() {
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final String commandStr = "say hello";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
@@ -115,15 +149,20 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
 
     @Test
     void skillLevelUpViaXPGainShouldRunCommandFiveTimesWithPlaceholders() {
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
-        assertEquals(mmoPlayer.getPlayer().getName(), playerName);
         final String commandStr = "say hello {@player}, you have reached level {@mining_level}";
-        final String expectedStr1 = "say hello " + playerName + ", you have reached level 1";
-        final String expectedStr2 = "say hello " + playerName + ", you have reached level 2";
-        final String expectedStr3 = "say hello " + playerName + ", you have reached level 3";
-        final String expectedStr4 = "say hello " + playerName + ", you have reached level 4";
-        final String expectedStr5 = "say hello " + playerName + ", you have reached level 5";
+        final String expectedStr1 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 1";
+        final String expectedStr2 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 2";
+        final String expectedStr3 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 3";
+        final String expectedStr4 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 4";
+        final String expectedStr5 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 5";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, skillLevel) -> skill == MINING && skillLevel >= 1 && skillLevel <= 5);
         mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
@@ -158,11 +197,11 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
             Each registered command runs only once.
          */
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
-        assertEquals(mmoPlayer.getPlayer().getName(), playerName);
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
 
         final String commandStr = "say hello {@player}";
-        final String expectedStr = "say hello " + playerName;
+        final String expectedStr = "say hello " + DEFAULT_PLAYER_NAME;
         final LevelUpCommand levelUpCommandOne = buildLevelUpCommand(commandStr,
                 (skill, level) -> skill == MINING && level == 1);
         mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandOne);
@@ -199,11 +238,11 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
             One command runs twice, the others run once.
          */
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
-        assertEquals(mmoPlayer.getPlayer().getName(), playerName);
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
 
         final String commandStr = "say hello {@player}";
-        final String expectedStr = "say hello " + playerName;
+        final String expectedStr = "say hello " + DEFAULT_PLAYER_NAME;
         final LevelUpCommand levelUpCommandOne = buildLevelUpCommand(commandStr,
                 (skill, level) -> skill == MINING && (level == 1 || level == 4));
         mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommandOne);
@@ -235,15 +274,20 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
     @Test
     void addLevelsShouldRunCommandFiveTimesWithPlaceholdersForLevel() {
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
-        assertEquals(mmoPlayer.getPlayer().getName(), playerName);
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
 
         final String commandStr = "say hello {@player}, you have reached level {@mining_level}";
-        final String expectedStr1 = "say hello " + playerName + ", you have reached level 1";
-        final String expectedStr2 = "say hello " + playerName + ", you have reached level 2";
-        final String expectedStr3 = "say hello " + playerName + ", you have reached level 3";
-        final String expectedStr4 = "say hello " + playerName + ", you have reached level 4";
-        final String expectedStr5 = "say hello " + playerName + ", you have reached level 5";
+        final String expectedStr1 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 1";
+        final String expectedStr2 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 2";
+        final String expectedStr3 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 3";
+        final String expectedStr4 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 4";
+        final String expectedStr5 =
+                "say hello " + DEFAULT_PLAYER_NAME + ", you have reached level 5";
 
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, ignored) -> skill == MINING);
@@ -251,32 +295,29 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
 
         // WHEN player gains 5 levels in mining
         int levelsGained = 5;
-        mmoPlayer.getProfile().addLevels(MINING, levelsGained);
-        EventUtils.tryLevelChangeEvent(
-                mmoPlayer.getPlayer(),
-                MINING,
-                levelsGained,
-                mmoPlayer.getProfile().getSkillXpLevelRaw(MINING),
-                true,
-                XPGainReason.COMMAND);
+        levelPlayerViaXP(mmoPlayer, MINING, levelsGained);
 
         // THEN the command should be checked for execution
-        verify(levelUpCommandManager).applySkillLevelUp(any(), any(), any(), any());
-        verify(levelUpCommand).process(any(), any(), any(), any());
+        verify(levelUpCommandManager, times(levelsGained))
+                .applySkillLevelUp(any(), any(), any(), any());
+        verify(levelUpCommand, times(levelsGained))
+                .process(any(), any(), any(), any());
         // THEN the command should have executed
-        verify(levelUpCommand, times(1)).executeCommand(any(McMMOPlayer.class));
+        verify(levelUpCommand, times(levelsGained))
+                .executeCommand(any(McMMOPlayer.class));
         // verify that Bukkit.dispatchCommand got executed at least 5 times with the correct injectedCommand
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr1)));
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr2)));
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr3)));
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr4)));
-        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr5)));
+        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr1)), atLeastOnce());
+        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr2)), atLeastOnce());
+        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr3)), atLeastOnce());
+        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr4)), atLeastOnce());
+        mockedBukkit.verify(() -> Bukkit.dispatchCommand(any(), eq(expectedStr5)), atLeastOnce());
     }
 
     @Test
     void skillLevelUpShouldRunCommandAtLeastOnce() {
         // GIVEN level up command for Mining should always execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final String commandStr = "say hello";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, ignored) -> skill == MINING);
@@ -298,7 +339,8 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
     @Test
     void skillLevelUpShouldNotRunCommand() {
         // GIVEN level up command for Woodcutting should not execute for Mining level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final String commandStr = "say hello";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr,
                 (skill, ignored) -> skill == WOODCUTTING);
@@ -320,7 +362,8 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
     @Test
     public void levelUpShouldAlwaysRunCommand() {
         // GIVEN level up command should always execute for any level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final String commandStr = "say hello";
         final LevelUpCommand levelUpCommand = buildLevelUpCommand(commandStr, ALWAYS_TRUE);
         mcMMO.p.getLevelUpCommandManager().registerCommand(levelUpCommand);
@@ -339,7 +382,8 @@ class LevelUpCommandTest extends MMOTestEnvironmentBasic {
     @Test
     public void skillLevelUpShouldRunPowerlevelCommandOnce() {
         // GIVEN level up command for power level should always execute for any level up
-        assert mcMMO.p.getLevelUpCommandManager().getLevelUpCommands().isEmpty();
+        final TestPlayerMock testPlayerMock = mockPlayer(UUID.randomUUID(), DEFAULT_PLAYER_NAME, 0);
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final String commandStr = "say hello";
         final LevelUpCommand powerLevelUpCommand = buildLevelUpCommand(commandStr,
                 (ignoredA, ignoredB) -> true, (powerlevel) -> powerlevel == 3);

+ 0 - 5
src/test/java/com/gmail/nossr50/config/CommandOnLevelUpConfigTest.java

@@ -1,5 +0,0 @@
-package com.gmail.nossr50.config;
-
-class CommandOnLevelUpConfigTest {
-
-}

+ 3 - 0
src/test/java/com/gmail/nossr50/party/PartyManagerTest.java

@@ -16,6 +16,7 @@ import com.gmail.nossr50.datatypes.party.Party;
 import com.gmail.nossr50.datatypes.party.PartyLeader;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.TestPlayerMock;
 import com.gmail.nossr50.util.player.NotificationManager;
 import com.gmail.nossr50.util.player.UserManager;
 import java.util.ArrayList;
@@ -144,6 +145,8 @@ class PartyManagerTest extends MMOTestEnvironment {
 
     @Test
     public void checkPartyExistenceReturnsTrueIfExists() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final Player player = testPlayerMock.player();
         PartyManager partyManager = new PartyManager(mcMMO.p);
 
         Party party = Mockito.mock(Party.class);

+ 10 - 3
src/test/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsTest.java

@@ -11,13 +11,16 @@ import static org.mockito.Mockito.when;
 
 import com.gmail.nossr50.MMOTestEnvironment;
 import com.gmail.nossr50.api.exceptions.InvalidSkillException;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
 import com.gmail.nossr50.datatypes.skills.subskills.acrobatics.Roll;
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.TestPlayerMock;
 import com.gmail.nossr50.util.skills.RankUtils;
 import java.util.logging.Logger;
+import org.bukkit.entity.Entity;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent;
 import org.jetbrains.annotations.NotNull;
@@ -62,9 +65,11 @@ class AcrobaticsTest extends MMOTestEnvironment {
     @Test
     public void rollShouldLowerDamage() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final Roll roll = new Roll();
         final double damage = 2D;
-        final EntityDamageEvent mockEvent = mockEntityDamageEvent(damage);
+        final EntityDamageEvent mockEvent = mockEntityDamageEvent(testPlayerMock.player(), damage);
         mmoPlayer.modifySkill(PrimarySkillType.ACROBATICS, 1000);
         when(roll.canRoll(mmoPlayer)).thenReturn(true);
         assertThat(roll.canRoll(mmoPlayer)).isTrue();
@@ -80,9 +85,11 @@ class AcrobaticsTest extends MMOTestEnvironment {
     @Test
     public void rollShouldNotLowerDamage() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         final Roll roll = new Roll();
         final double damage = 100D;
-        final EntityDamageEvent mockEvent = mockEntityDamageEvent(damage);
+        final EntityDamageEvent mockEvent = mockEntityDamageEvent(testPlayerMock.player(), damage);
         mmoPlayer.modifySkill(PrimarySkillType.ACROBATICS, 0);
         when(roll.canRoll(mmoPlayer)).thenReturn(true);
         assertThat(roll.canRoll(mmoPlayer)).isTrue();
@@ -95,7 +102,7 @@ class AcrobaticsTest extends MMOTestEnvironment {
         verify(mockEvent, Mockito.never()).setDamage(any(Double.class));
     }
 
-    private @NotNull EntityDamageEvent mockEntityDamageEvent(double damage) {
+    private @NotNull EntityDamageEvent mockEntityDamageEvent(Entity player, double damage) {
         final EntityDamageEvent mockEvent = mock(EntityDamageEvent.class);
         when(mockEvent.isApplicable(any(EntityDamageEvent.DamageModifier.class))).thenReturn(true);
         when(mockEvent.getCause()).thenReturn(EntityDamageEvent.DamageCause.FALL);

+ 10 - 8
src/test/java/com/gmail/nossr50/skills/excavation/ExcavationTest.java

@@ -10,9 +10,11 @@ import static org.mockito.Mockito.when;
 
 import com.gmail.nossr50.MMOTestEnvironment;
 import com.gmail.nossr50.api.exceptions.InvalidSkillException;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.datatypes.treasure.ExcavationTreasure;
+import com.gmail.nossr50.util.TestPlayerMock;
 import com.gmail.nossr50.util.skills.RankUtils;
 import java.util.ArrayList;
 import java.util.List;
@@ -48,14 +50,6 @@ class ExcavationTest extends MMOTestEnvironment {
                 eq(SubSkillType.EXCAVATION_ARCHAEOLOGY))).thenReturn(true);
         when(RankUtils.hasReachedRank(eq(1), any(Player.class),
                 eq(SubSkillType.EXCAVATION_GIGA_DRILL_BREAKER))).thenReturn(true);
-
-        // setup player and player related mocks after everything else
-        this.player = Mockito.mock(Player.class);
-        when(player.getUniqueId()).thenReturn(playerUUID);
-
-        // wire inventory
-        this.itemInMainHand = new ItemStack(Material.DIAMOND_SHOVEL);
-        when(playerInventory.getItemInMainHand()).thenReturn(itemInMainHand);
     }
 
     @AfterEach
@@ -65,6 +59,10 @@ class ExcavationTest extends MMOTestEnvironment {
 
     @Test
     void excavationShouldHaveTreasureDrops() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_SHOVEL));
         mmoPlayer.modifySkill(PrimarySkillType.EXCAVATION, 1000);
 
         // Wire block
@@ -83,6 +81,10 @@ class ExcavationTest extends MMOTestEnvironment {
 
     @Test
     void excavationShouldNotDropTreasure() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_SHOVEL));
         mmoPlayer.modifySkill(PrimarySkillType.EXCAVATION, 1000);
 
         // Wire block

+ 43 - 43
src/test/java/com/gmail/nossr50/skills/tridents/TridentsTest.java

@@ -1,43 +1,43 @@
-package com.gmail.nossr50.skills.tridents;
-
-import static java.util.logging.Logger.getLogger;
-
-import com.gmail.nossr50.MMOTestEnvironment;
-import com.gmail.nossr50.api.exceptions.InvalidSkillException;
-import java.util.logging.Logger;
-import org.bukkit.Material;
-import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.PlayerInventory;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.mockito.Mockito;
-
-class TridentsTest extends MMOTestEnvironment {
-    private static final Logger logger = getLogger(TridentsTest.class.getName());
-
-    TridentsManager tridentsManager;
-    ItemStack trident;
-
-    @BeforeEach
-    void setUp() throws InvalidSkillException {
-        mockBaseEnvironment(logger);
-
-        // setup player and player related mocks after everything else
-        this.player = Mockito.mock(Player.class);
-        Mockito.when(player.getUniqueId()).thenReturn(playerUUID);
-
-        // wire inventory
-        this.playerInventory = Mockito.mock(PlayerInventory.class);
-        this.trident = new ItemStack(Material.TRIDENT);
-        Mockito.when(playerInventory.getItemInMainHand()).thenReturn(trident);
-
-        // Set up spy for manager
-        tridentsManager = Mockito.spy(new TridentsManager(mmoPlayer));
-    }
-
-    @AfterEach
-    void tearDown() {
-        cleanUpStaticMocks();
-    }
-}
+//package com.gmail.nossr50.skills.tridents;
+//
+//import static java.util.logging.Logger.getLogger;
+//
+//import com.gmail.nossr50.MMOTestEnvironment;
+//import com.gmail.nossr50.api.exceptions.InvalidSkillException;
+//import java.util.logging.Logger;
+//import org.bukkit.Material;
+//import org.bukkit.entity.Player;
+//import org.bukkit.inventory.ItemStack;
+//import org.bukkit.inventory.PlayerInventory;
+//import org.junit.jupiter.api.AfterEach;
+//import org.junit.jupiter.api.BeforeEach;
+//import org.mockito.Mockito;
+//
+//class TridentsTest extends MMOTestEnvironment {
+//    private static final Logger logger = getLogger(TridentsTest.class.getName());
+//
+//    TridentsManager tridentsManager;
+//    ItemStack trident;
+//
+//    @BeforeEach
+//    void setUp() throws InvalidSkillException {
+//        mockBaseEnvironment(logger);
+//
+//        // setup player and player related mocks after everything else
+//        this.player = Mockito.mock(Player.class);
+//        Mockito.when(player.getUniqueId()).thenReturn(playerUUID);
+//
+//        // wire inventory
+//        this.playerInventory = Mockito.mock(PlayerInventory.class);
+//        this.trident = new ItemStack(Material.TRIDENT);
+//        Mockito.when(playerInventory.getItemInMainHand()).thenReturn(trident);
+//
+//        // Set up spy for manager
+//        tridentsManager = Mockito.spy(new TridentsManager(mmoPlayer));
+//    }
+//
+//    @AfterEach
+//    void tearDown() {
+//        cleanUpStaticMocks();
+//    }
+//}

+ 41 - 26
src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java

@@ -9,14 +9,17 @@ import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
 
 import com.gmail.nossr50.MMOTestEnvironment;
 import com.gmail.nossr50.api.exceptions.InvalidSkillException;
 import com.gmail.nossr50.config.experience.ExperienceConfig;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.BlockUtils;
+import com.gmail.nossr50.util.TestPlayerMock;
 import com.gmail.nossr50.util.skills.RankUtils;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -40,15 +43,13 @@ import org.mockito.Mockito;
 class WoodcuttingTest extends MMOTestEnvironment {
     private static final Logger logger = getLogger(WoodcuttingTest.class.getName());
 
-    private WoodcuttingManager woodcuttingManager;
-
     @BeforeEach
     void setUp() throws InvalidSkillException {
         mockBaseEnvironment(logger);
+        // TODO: can move the rest of these to a beforeAll
         Mockito.when(rankConfig.getSubSkillUnlockLevel(SubSkillType.WOODCUTTING_HARVEST_LUMBER, 1))
                 .thenReturn(1);
 
-        // wire advanced config
         Mockito.when(advancedConfig.getMaximumProbability(SubSkillType.WOODCUTTING_HARVEST_LUMBER))
                 .thenReturn(100D);
         Mockito.when(advancedConfig.getMaximumProbability(SubSkillType.WOODCUTTING_CLEAN_CUTS))
@@ -66,14 +67,6 @@ class WoodcuttingTest extends MMOTestEnvironment {
                 eq(SubSkillType.WOODCUTTING_HARVEST_LUMBER))).thenReturn(true);
         Mockito.when(RankUtils.hasReachedRank(eq(1), any(Player.class),
                 eq(SubSkillType.WOODCUTTING_CLEAN_CUTS))).thenReturn(true);
-
-        // wire inventory
-        this.itemInMainHand = new ItemStack(Material.DIAMOND_AXE);
-        Mockito.when(player.getInventory()).thenReturn(playerInventory);
-        Mockito.when(playerInventory.getItemInMainHand()).thenReturn(itemInMainHand);
-
-        // Set up spy for WoodcuttingManager
-        woodcuttingManager = Mockito.spy(new WoodcuttingManager(mmoPlayer));
     }
 
     @AfterEach
@@ -83,6 +76,12 @@ class WoodcuttingTest extends MMOTestEnvironment {
 
     @Test
     void harvestLumberShouldDoubleDrop() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_AXE));
+        final WoodcuttingManager woodcuttingManager = Mockito.spy(
+                new WoodcuttingManager(mmoPlayer));
         mmoPlayer.modifySkill(PrimarySkillType.WOODCUTTING, 1000);
 
         Block block = mock(Block.class);
@@ -100,6 +99,12 @@ class WoodcuttingTest extends MMOTestEnvironment {
 
     @Test
     void harvestLumberShouldNotDoubleDrop() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_AXE));
+        final WoodcuttingManager woodcuttingManager = Mockito.spy(
+                new WoodcuttingManager(mmoPlayer));
         mmoPlayer.modifySkill(PrimarySkillType.WOODCUTTING, 0);
 
         Block block = mock(Block.class);
@@ -115,6 +120,12 @@ class WoodcuttingTest extends MMOTestEnvironment {
 
     @Test
     void testProcessWoodcuttingBlockXP() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_AXE));
+        final WoodcuttingManager woodcuttingManager = Mockito.spy(
+                new WoodcuttingManager(mmoPlayer));
         Block targetBlock = mock(Block.class);
         Mockito.when(targetBlock.getType()).thenReturn(Material.OAK_LOG);
         // wire XP
@@ -129,11 +140,15 @@ class WoodcuttingTest extends MMOTestEnvironment {
 
     @Test
     void treeFellerShouldStopAtThreshold() {
-        // Set threshold artificially low
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_AXE));
+        // Set threshold to 3
         int fakeThreshold = 3;
         Mockito.when(generalConfig.getTreeFellerThreshold()).thenReturn(fakeThreshold);
-
-        WoodcuttingManager manager = Mockito.spy(new WoodcuttingManager(mmoPlayer));
+        final WoodcuttingManager woodcuttingManager = Mockito.spy(
+                new WoodcuttingManager(mmoPlayer));
 
         // Simulate all blocks are logs with XP
         MockedStatic<BlockUtils> mockedBlockUtils = mockStatic(BlockUtils.class);
@@ -163,7 +178,7 @@ class WoodcuttingTest extends MMOTestEnvironment {
                         ThreadLocalRandom.current().nextInt(relatives.size())));
 
         Set<Block> treeFellerBlocks = new HashSet<>();
-        manager.processTree(centerBlock, treeFellerBlocks);
+        woodcuttingManager.processTree(centerBlock, treeFellerBlocks);
 
         // --- Assertions ---
 
@@ -171,12 +186,8 @@ class WoodcuttingTest extends MMOTestEnvironment {
         assertFalse(treeFellerBlocks.isEmpty(), "Tree Feller should process at least one block");
 
         // It reached or slightly exceeded the threshold
-        assertTrue(treeFellerBlocks.size() >= fakeThreshold,
-                "Tree Feller should process up to the threshold limit");
-
-        // Confirm it stopped due to the threshold
-        assertTrue(getPrivateTreeFellerReachedThreshold(manager),
-                "Tree Feller should set treeFellerReachedThreshold to true");
+        assertEquals(fakeThreshold, treeFellerBlocks.size(),
+                "expected that Tree Feller will have a block size equal to the threshold");
 
         mockedBlockUtils.close();
     }
@@ -192,12 +203,16 @@ class WoodcuttingTest extends MMOTestEnvironment {
     }
 
     @Test
-    void treeFellerShouldNotReachThreshold() throws NoSuchFieldException, IllegalAccessException {
+    void treeFellerShouldNotReachThreshold() {
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
+        when(testPlayerMock.playerInventory().getItemInMainHand())
+                .thenReturn(new ItemStack(Material.DIAMOND_AXE));
+        final WoodcuttingManager woodcuttingManager = Mockito.spy(
+                new WoodcuttingManager(mmoPlayer));
         int threshold = 10;
         Mockito.when(generalConfig.getTreeFellerThreshold()).thenReturn(threshold);
 
-        WoodcuttingManager manager = Mockito.spy(new WoodcuttingManager(mmoPlayer));
-
         MockedStatic<BlockUtils> mockedBlockUtils = mockStatic(BlockUtils.class);
         mockedBlockUtils.when(() -> BlockUtils.hasWoodcuttingXP(any(Block.class))).thenReturn(true);
         mockedBlockUtils.when(() -> BlockUtils.isNonWoodPartOfTree(any(Block.class)))
@@ -222,10 +237,10 @@ class WoodcuttingTest extends MMOTestEnvironment {
         Mockito.when(b3.getRelative(any(BlockFace.class))).thenReturn(null);
 
         Set<Block> processed = new HashSet<>();
-        manager.processTree(b0, processed);
+        woodcuttingManager.processTree(b0, processed);
 
         assertEquals(3, processed.size(), "Should process exactly 4 blocks");
-        assertFalse(getPrivateTreeFellerReachedThreshold(manager),
+        assertFalse(getPrivateTreeFellerReachedThreshold(woodcuttingManager),
                 "treeFellerReachedThreshold should remain false");
 
         mockedBlockUtils.close();

+ 60 - 60
src/test/java/com/gmail/nossr50/util/PotionEffectUtilTest.java

@@ -1,60 +1,60 @@
-package com.gmail.nossr50.util;
-
-import static com.gmail.nossr50.util.PotionEffectUtil.getNauseaPotionEffectType;
-import static java.util.logging.Logger.getLogger;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.when;
-
-import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.util.compat.CompatibilityManager;
-import com.gmail.nossr50.util.platform.MinecraftGameVersion;
-import org.bukkit.potion.PotionEffectType;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Tag;
-import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
-
-class PotionEffectUtilTest {
-    private MockedStatic<mcMMO> mockedStaticMcMMO;
-    private static final java.util.logging.Logger logger = getLogger(
-            PotionEffectUtilTest.class.getName());
-
-    @BeforeEach
-    void setUp() {
-        mockedStaticMcMMO = mockStatic(mcMMO.class);
-        mcMMO.p = mock(mcMMO.class);
-        when(mcMMO.p.getLogger()).thenReturn(logger);
-        CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
-        MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
-        when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
-        when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false);
-        when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
-    }
-
-    @AfterEach
-    void tearDown() {
-        mockedStaticMcMMO.close();
-    }
-
-    @Test
-    @Tag("skip")
-    void testGetNauseaPotionEffectType() {
-        // TODO: Test only works on older versions since we aren't properly mocking the spigot registry
-        final PotionEffectType nausea = getNauseaPotionEffectType();
-        assertNotNull(nausea);
-        assertThat(nausea).isEqualTo(PotionEffectType.NAUSEA);
-    }
-
-    @Test
-    @Tag("skip")
-    void testGetHastePotionEffectType() {
-        // TODO: Test only works on older versions since we aren't properly mocking the spigot registry
-        final PotionEffectType haste = PotionEffectUtil.getHastePotionEffectType();
-        assertNotNull(haste);
-        assertThat(haste).isEqualTo(PotionEffectType.HASTE);
-    }
-}
+//package com.gmail.nossr50.util;
+//
+//import static com.gmail.nossr50.util.PotionEffectUtil.getNauseaPotionEffectType;
+//import static java.util.logging.Logger.getLogger;
+//import static org.assertj.core.api.Assertions.assertThat;
+//import static org.junit.jupiter.api.Assertions.assertNotNull;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.mockStatic;
+//import static org.mockito.Mockito.when;
+//
+//import com.gmail.nossr50.mcMMO;
+//import com.gmail.nossr50.util.compat.CompatibilityManager;
+//import com.gmail.nossr50.util.platform.MinecraftGameVersion;
+//import org.bukkit.potion.PotionEffectType;
+//import org.junit.jupiter.api.AfterEach;
+//import org.junit.jupiter.api.BeforeEach;
+//import org.junit.jupiter.api.Tag;
+//import org.junit.jupiter.api.Test;
+//import org.mockito.MockedStatic;
+//
+//class PotionEffectUtilTest {
+//    private MockedStatic<mcMMO> mockedStaticMcMMO;
+//    private static final java.util.logging.Logger logger = getLogger(
+//            PotionEffectUtilTest.class.getName());
+//
+//    @BeforeEach
+//    void setUp() {
+//        mockedStaticMcMMO = mockStatic(mcMMO.class);
+//        mcMMO.p = mock(mcMMO.class);
+//        when(mcMMO.p.getLogger()).thenReturn(logger);
+//        CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
+//        MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
+//        when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
+//        when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(false);
+//        when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
+//    }
+//
+//    @AfterEach
+//    void tearDown() {
+//        mockedStaticMcMMO.close();
+//    }
+//
+//    @Test
+//    @Tag("skip")
+//    void testGetNauseaPotionEffectType() {
+//        // TODO: Test only works on older versions since we aren't properly mocking the spigot registry
+//        final PotionEffectType nausea = getNauseaPotionEffectType();
+//        assertNotNull(nausea);
+//        assertThat(nausea).isEqualTo(PotionEffectType.NAUSEA);
+//    }
+//
+//    @Test
+//    @Tag("skip")
+//    void testGetHastePotionEffectType() {
+//        // TODO: Test only works on older versions since we aren't properly mocking the spigot registry
+//        final PotionEffectType haste = PotionEffectUtil.getHastePotionEffectType();
+//        assertNotNull(haste);
+//        assertThat(haste).isEqualTo(PotionEffectType.HASTE);
+//    }
+//}

+ 12 - 0
src/test/java/com/gmail/nossr50/util/TestPlayerMock.java

@@ -0,0 +1,12 @@
+package com.gmail.nossr50.util;
+
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.datatypes.player.PlayerProfile;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.PlayerInventory;
+
+public record TestPlayerMock(Player player, PlayerInventory playerInventory,
+                             Location playerLocation, PlayerProfile playerProfile,
+                             McMMOPlayer mmoPlayer) {
+}

+ 16 - 0
src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java

@@ -15,7 +15,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.when;
 
 import com.gmail.nossr50.MMOTestEnvironment;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.SubSkillType;
+import com.gmail.nossr50.util.TestPlayerMock;
 import java.util.logging.Logger;
 import java.util.stream.Stream;
 import org.junit.jupiter.api.AfterEach;
@@ -66,6 +68,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void isSkillRNGSuccessfulShouldBehaveAsExpected() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(UNARMED_ARROW_DEFLECT)).thenReturn(20D);
         when(advancedConfig.getMaxBonusLevel(UNARMED_ARROW_DEFLECT)).thenReturn(0);
 
@@ -110,6 +114,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn10PercentForDodge() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
         when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
         mmoPlayer.modifySkill(ACROBATICS, 500);
@@ -123,6 +129,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn20PercentForDodge() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
         when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
         mmoPlayer.modifySkill(ACROBATICS, 1000);
@@ -136,6 +144,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn0PercentForDodge() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(ACROBATICS_DODGE)).thenReturn(20D);
         when(advancedConfig.getMaxBonusLevel(ACROBATICS_DODGE)).thenReturn(1000);
         mmoPlayer.modifySkill(ACROBATICS, 0);
@@ -149,6 +159,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn10PercentForDoubleDrops() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
         when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
         mmoPlayer.modifySkill(MINING, 100);
@@ -162,6 +174,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn50PercentForDoubleDrops() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
         when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
         mmoPlayer.modifySkill(MINING, 500);
@@ -175,6 +189,8 @@ class ProbabilityUtilTest extends MMOTestEnvironment {
     @Test
     public void getRNGDisplayValuesShouldReturn100PercentForDoubleDrops() {
         // Given
+        final TestPlayerMock testPlayerMock = mockPlayer();
+        final McMMOPlayer mmoPlayer = testPlayerMock.mmoPlayer();
         when(advancedConfig.getMaximumProbability(MINING_DOUBLE_DROPS)).thenReturn(100D);
         when(advancedConfig.getMaxBonusLevel(MINING_DOUBLE_DROPS)).thenReturn(1000);
         mmoPlayer.modifySkill(MINING, 1000);