From 20386462ce96f270d2cc7e4a33bd2bfba9f5d90f Mon Sep 17 00:00:00 2001 From: leriomaggio Date: Wed, 9 Jun 2021 17:01:04 +0100 Subject: [PATCH] Base PowerMock Test case for CardDb testing This base class will be used throughout the tests whenever Card Database (Mocks) will be required for testing. This will be the case (for example) of tests for CardRequest, CardEdition, CardDb. --- .../forge/card/ForgeCardMockTestCase.java | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java diff --git a/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java b/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java new file mode 100644 index 00000000000..58a53836a6f --- /dev/null +++ b/forge-gui-desktop/src/test/java/forge/card/ForgeCardMockTestCase.java @@ -0,0 +1,167 @@ +package forge.card; + +import forge.ImageCache; +import forge.ImageKeys; +import forge.Singletons; +import forge.StaticData; +import forge.gamesimulationtests.util.CardDatabaseHelper; +import forge.item.PaperCard; +import forge.localinstance.properties.ForgeConstants; +import forge.localinstance.properties.ForgePreferences; +import forge.model.FModel; +import forge.util.Localizer; +import forge.util.TextUtil; +import org.apache.commons.lang3.StringUtils; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.testng.PowerMockTestCase; +import org.testng.IObjectFactory; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.ObjectFactory; + +import javax.imageio.ImageIO; +import java.io.File; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Locale; +import java.util.ResourceBundle; + +@PrepareForTest(value = {FModel.class, Singletons.class, ResourceBundle.class, + ImageCache.class, ImageIO.class, ImageKeys.class, + ForgeConstants.class, Localizer.class}) +@SuppressStaticInitializationFor({"forge.ImageCache", "forge.localinstance.properties.ForgeConstants"}) +public class ForgeCardMockTestCase extends PowerMockTestCase { + + private static String getUserDir() { + // Adapted - reduced version from ForgeProfileProperties (which is private) + final String osName = System.getProperty("os.name"); + final String homeDir = System.getProperty("user.home"); + + if (StringUtils.isEmpty(osName) || StringUtils.isEmpty(homeDir)) { + throw new RuntimeException("cannot determine OS and user home directory"); + } + + final String fallbackDataDir = TextUtil.concatNoSpace(homeDir, "/.forge/"); + + if (StringUtils.containsIgnoreCase(osName, "windows")) { + String appRoot = System.getenv().get("APPDATA"); + if (StringUtils.isEmpty(appRoot)) { + appRoot = fallbackDataDir; + } + return appRoot + File.separator + "Forge" + File.separator; + } else if (StringUtils.containsIgnoreCase(osName, "mac os x")) { + return TextUtil.concatNoSpace(homeDir, "/Library/Application Support/Forge/"); + } + // Linux and everything else + return fallbackDataDir; + } + + private void initForgeConstants() throws IllegalAccessException { + PowerMockito.mockStatic(ForgeConstants.class); + // Path Sep + Field fPathSep = PowerMockito.field(ForgeConstants.class, "PATH_SEPARATOR"); + fPathSep.set(ForgeConstants.class, File.separator); + // Assets Dir + String assetDir = "../forge-gui/"; + Field fAssetsDir = PowerMockito.field(ForgeConstants.class, "ASSETS_DIR"); + fAssetsDir.set(ForgeConstants.class, assetDir); + // User Dir + String homeDir = ForgeCardMockTestCase.getUserDir(); + Field fUserDir = PowerMockito.field(ForgeConstants.class, "USER_DIR"); + fUserDir.set(ForgeConstants.class, homeDir); + // User Pref Dir + String prefDir = homeDir + "preferences" + File.separator; + Field fUserPrefsDir = PowerMockito.field(ForgeConstants.class, "USER_PREFS_DIR"); + fUserPrefsDir.set(ForgeConstants.class, prefDir); + // Main Pref File + String mainPrefFile = prefDir + "forge.preferences"; + Field fMainPrefFile = PowerMockito.field(ForgeConstants.class, "MAIN_PREFS_FILE"); + fMainPrefFile.set(ForgeConstants.class, mainPrefFile); + // Res Dir + String resDir = assetDir + "res" + File.separator; + Field fResDir = PowerMockito.field(ForgeConstants.class, "RES_DIR"); + fResDir.set(ForgeConstants.class, resDir); + // Card Data Dir + String cardDir = resDir + "cardsfolder" + File.separator; + Field fCardDataDir = PowerMockito.field(ForgeConstants.class, "CARD_DATA_DIR"); + fCardDataDir.set(ForgeConstants.class, cardDir); + // Editions Dir + String editionsDir = resDir + "editions" + File.separator; + Field fEditionsDir = PowerMockito.field(ForgeConstants.class, "EDITIONS_DIR"); + fEditionsDir.set(ForgeConstants.class, editionsDir); + // Block Data Dir + String blockDataDir = resDir + "blockdata" + File.separator; + Field fBlockData = PowerMockito.field(ForgeConstants.class, "BLOCK_DATA_DIR"); + fBlockData.set(ForgeConstants.class, blockDataDir); + // User Custom Dir + String userCustomDir = homeDir + "custom" + File.separator; + Field fUserCustomDir = PowerMockito.field(ForgeConstants.class, "USER_CUSTOM_DIR"); + fUserCustomDir.set(ForgeConstants.class, userCustomDir); + // User Custom card Dir + String userCustomCardDir = userCustomDir + "cards" + File.separator; + Field fUserCustoCardDir = PowerMockito.field(ForgeConstants.class, "USER_CUSTOM_CARDS_DIR"); + fUserCustoCardDir.set(ForgeConstants.class, userCustomCardDir); + // User Custom Edition Dir + String userCustomEditionDir = userCustomDir + "editions" + File.separator; + Field fUserCustomEditionDir = PowerMockito.field(ForgeConstants.class, "USER_CUSTOM_EDITIONS_DIR"); + fUserCustomEditionDir.set(ForgeConstants.class, userCustomEditionDir); + } + + private void setMock(Localizer mock) { + try { + Field instance = Localizer.class.getDeclaredField("instance"); + instance.setAccessible(true); + instance.set(instance, mock); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @BeforeMethod + protected void initMocks() throws Exception { + //Loading a card also automatically loads the image, which we do not want (even if it wouldn't cause exceptions). + //The static initializer block in ImageCache can't fully be mocked (https://code.google.com/p/powermock/issues/detail?id=256), so we also need to mess with ImageIO... + //TODO: make sure that loading images only happens in a GUI environment, so we no longer need to mock this + PowerMockito.mockStatic(ImageIO.class); + PowerMockito.mockStatic(ImageCache.class); + PowerMockito.mockStatic(ImageKeys.class); + PowerMockito.when(ImageKeys.hasImage(Mockito.any(PaperCard.class))).thenReturn(true); + initForgeConstants(); + + //Mocking some more static stuff + PowerMockito.mockStatic(Singletons.class); + PowerMockito.mockStatic(FModel.class); + ForgePreferences forgePreferences = new ForgePreferences(); + + ResourceBundle dummyResourceBundle = new ResourceBundle() { + @Override + protected Object handleGetObject(String key) { + return key; + } + + @Override + public Enumeration getKeys() { + return Collections.emptyEnumeration(); + } + }; + + PowerMockito.mockStatic(ResourceBundle.class); + PowerMockito.when(ResourceBundle.getBundle("en-US", Locale.ENGLISH)).thenReturn(dummyResourceBundle); + Localizer localizerMock = PowerMockito.mock(Localizer.class); + setMock(localizerMock); + PowerMockito.field(Localizer.class, "resourceBundle").set(localizerMock, dummyResourceBundle); + PowerMockito.when(localizerMock.getMessage(Mockito.anyString())).thenReturn("any string"); + + PowerMockito.when(FModel.getPreferences()).thenReturn(forgePreferences); + StaticData data = CardDatabaseHelper.getStaticDataToPopulateOtherMocks(); + PowerMockito.when(FModel.getMagicDb()).thenReturn(data); + } + + @ObjectFactory + public IObjectFactory getObjectFactory() { + return new org.powermock.modules.testng.PowerMockObjectFactory(); + } +}