Fix test environment writing config files to project root

BukkitConfig calls mcMMO.p.getDataFolder() in its constructor to
determine where to write config files. When tests mock mcMMO.p but
don't stub getDataFolder(), it returns null, which Java resolves to
the current working directory (the project root), causing files like
experience.yml to be created there.

Fix by stubbing mcMMO.p.getDataFolder() with a fresh temporary
directory in every test setup that mocks mcMMO.p:
- MMOTestEnvironment.mockBaseEnvironment(): creates testDataFolder
  in temp and deletes it in cleanUpStaticMocks()
- SQLDatabaseManagerTest.setUpAll(): same pattern, cleaned in tearDownAll()
- FlatFileDatabaseManagerTest.initBeforeAll(): same pattern, cleaned
  in the new tearDownAll() method

Also remove the .gitignore band-aid entries that were added to paper
over the symptom.
This commit is contained in:
nossr50
2026-05-30 22:58:37 -07:00
parent 3a69634a33
commit 2ec35ed0cc
4 changed files with 65 additions and 11 deletions

11
.gitignore vendored
View File

@ -50,17 +50,6 @@
# Project Stuff
/src/main/resources/mcMMO
# Config files that tests can accidentally write to the project root
# when mcMMO.p.getDataFolder() returns null (resolves to cwd)
/experience.yml
/config.yml
/advanced.yml
/fishing_treasures.yml
/treasures.yml
/sounds.yml
/potions.yml
/skillranks.yml
# Other Libraries
*.jar

View File

@ -30,6 +30,8 @@ import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.sounds.SoundManager;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
@ -85,11 +87,18 @@ public abstract class MMOTestEnvironment {
protected MaterialMapStore materialMapStore;
protected MinecraftGameVersion minecraftGameVersion;
protected File testDataFolder;
protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException {
mockedMcMMO = mockStatic(mcMMO.class);
mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
try {
testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-test-data-").toFile();
} catch (IOException e) {
throw new RuntimeException("Failed to create temp test data folder", e);
}
when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder);
// Game version
minecraftGameVersion = mock(MinecraftGameVersion.class);
@ -279,5 +288,21 @@ public abstract class MMOTestEnvironment {
if (mockedSoundManager != null) {
mockedSoundManager.close();
}
if (testDataFolder != null) {
deleteRecursively(testDataFolder);
testDataFolder = null;
}
}
private static void deleteRecursively(final File file) {
if (file.isDirectory()) {
final File[] children = file.listFiles();
if (children != null) {
for (final File child : children) {
deleteRecursively(child);
}
}
}
file.delete();
}
}

View File

@ -45,6 +45,7 @@ import java.util.logging.Logger;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -55,6 +56,8 @@ import org.mockito.Mockito;
@Tag("docker")
class FlatFileDatabaseManagerTest {
private static File testDataFolder;
public static final @NotNull String TEST_FILE_NAME = "test.mcmmo.users";
public static final @NotNull String BAD_FILE_LINE_ONE = "mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:";
public static final @NotNull String BAD_DATA_FILE_LINE_TWENTY_THREE = "nossr51:baddata:::baddata:baddata:640:baddata:1000:1000:1000:baddata:baddata:baddata:baddata:16:0:500:20273:0:0:0:0::1000:0:0:baddata:1593543012:0:0:0:0::1000:0:0:baddata:IGNORED:1000:0:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1:0:";
@ -100,6 +103,12 @@ class FlatFileDatabaseManagerTest {
// GIVEN a fully mocked mcMMO environment
mcMMO.p = Mockito.mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
try {
testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-flatfile-test-data-").toFile();
} catch (java.io.IOException e) {
throw new RuntimeException("Failed to create temp test data folder", e);
}
when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder);
// Null player lookup, shouldn't affect tests
Server server = mock(Server.class);
@ -118,6 +127,13 @@ class FlatFileDatabaseManagerTest {
return tempDir.getPath() + File.separator + TEST_FILE_NAME;
}
@AfterAll
static void tearDownAll() {
if (testDataFolder != null) {
recursiveDelete(testDataFolder);
}
}
@AfterEach
void tearDown() {
recursiveDelete(tempDir);

View File

@ -25,6 +25,8 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.upgrade.UpgradeManager;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
@ -82,6 +84,7 @@ class SQLDatabaseManagerTest {
private static UpgradeManager upgradeManager;
private static SkillTools skillTools;
private static MinecraftGameVersion minecraftGameVersion;
private static File testDataFolder;
// --- DB flavors you support ---
enum DbFlavor {
@ -102,6 +105,12 @@ class SQLDatabaseManagerTest {
mockedMcMMO = Mockito.mockStatic(mcMMO.class);
mcMMO.p = Mockito.mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
try {
testDataFolder = java.nio.file.Files.createTempDirectory("mcmmo-sql-test-data-").toFile();
} catch (IOException e) {
throw new RuntimeException("Failed to create temp test data folder", e);
}
when(mcMMO.p.getDataFolder()).thenReturn(testDataFolder);
when(mcMMO.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
mockGeneralConfigBase();
@ -127,6 +136,21 @@ class SQLDatabaseManagerTest {
@AfterAll
static void tearDownAll() {
mockedMcMMO.close();
if (testDataFolder != null) {
deleteRecursively(testDataFolder);
}
}
private static void deleteRecursively(final File file) {
if (file.isDirectory()) {
final File[] children = file.listFiles();
if (children != null) {
for (final File child : children) {
deleteRecursively(child);
}
}
}
file.delete();
}
private static void mockGeneralConfigBase() {