From 45ae7508826d0ca28b365060e478ed01071cce1c Mon Sep 17 00:00:00 2001 From: Oliver Bertuch Date: Mon, 22 Nov 2021 15:50:45 +0100 Subject: [PATCH] feat(api-test): add new JUnit5 extension @DBSetting #8251 This extension allows to set and reset database settings within a target Dataverse instance. It will make sure to reset to old setting or remove the setting if not set before the test. This was introduced for three reasons: 1. Don't execute a test if the setting did not go through 2. Don't forget to reset or remove to keep a consistent state after a test execution 3. Make the code more readable, as setting the setting has been part of the test before (which is bad design and might go booboo, see 2) --- .../edu/harvard/iq/dataverse/api/UtilIT.java | 6 +- .../iq/dataverse/api/helpers/DBSetting.java | 19 +++++ .../api/helpers/DBSettingExtension.java | 78 +++++++++++++++++++ .../iq/dataverse/api/helpers/DBSettings.java | 15 ++++ 4 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSetting.java create mode 100644 src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettingExtension.java create mode 100644 src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettings.java diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java index 03145f4c01b..52496ca614d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java @@ -1780,17 +1780,17 @@ static Response enableSetting(SettingsServiceBean.Key settingKey) { return response; } - static Response deleteSetting(SettingsServiceBean.Key settingKey) { + public static Response deleteSetting(SettingsServiceBean.Key settingKey) { Response response = given().when().delete("/api/admin/settings/" + settingKey); return response; } - static Response getSetting(SettingsServiceBean.Key settingKey) { + public static Response getSetting(SettingsServiceBean.Key settingKey) { Response response = given().when().get("/api/admin/settings/" + settingKey); return response; } - static Response setSetting(SettingsServiceBean.Key settingKey, String value) { + public static Response setSetting(SettingsServiceBean.Key settingKey, String value) { Response response = given().body(value).when().put("/api/admin/settings/" + settingKey); return response; } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSetting.java b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSetting.java new file mode 100644 index 00000000000..cd5bd1dc6d4 --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSetting.java @@ -0,0 +1,19 @@ +package edu.harvard.iq.dataverse.api.helpers; + +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Repeatable(value = DBSettings.class) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(DBSettingExtension.class) +public @interface DBSetting { + SettingsServiceBean.Key name(); + String value(); +} diff --git a/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettingExtension.java b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettingExtension.java new file mode 100644 index 00000000000..8c14cfb9b16 --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettingExtension.java @@ -0,0 +1,78 @@ +package edu.harvard.iq.dataverse.api.helpers; + +import com.jayway.restassured.response.Response; +import edu.harvard.iq.dataverse.api.UtilIT; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.extension.AfterTestExecutionCallback; +import org.junit.jupiter.api.extension.BeforeTestExecutionCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; + +import javax.servlet.http.HttpServletResponse; +import java.util.logging.Logger; + +public class DBSettingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback { + + private static final Logger logger = Logger.getLogger(DBSettingExtension.class.getCanonicalName()); + + private Store getStore(ExtensionContext context) { + return context.getStore(Namespace.create(getClass(), context.getRequiredTestClass(), context.getRequiredTestMethod())); + } + + @Override + public void beforeTestExecution(ExtensionContext extensionContext) throws Exception { + extensionContext.getTestMethod().ifPresent(method -> { + DBSetting[] settings = method.getAnnotationsByType(DBSetting.class); + for (DBSetting setting : settings) { + // get the setting ... + Response getSetting = UtilIT.getSetting(setting.name()); + if (getSetting.getStatusCode() == HttpServletResponse.SC_OK) { + String oldSetting = getSetting.getBody().jsonPath().getString("data.message"); + logger.fine("Found former value \""+oldSetting+"\" for "+setting.name()+"."); + // ... and store in context to restore later + getStore(extensionContext).put(setting.name(), oldSetting); + } else if (getSetting.getStatusCode() == HttpServletResponse.SC_NOT_FOUND) { + logger.fine("No former value for "+setting.name()+" present."); + // do nothing - will delete setting later + } else { + Assumptions.assumeTrue( + getSetting.getStatusCode() == HttpServletResponse.SC_OK || + getSetting.getStatusCode() == HttpServletResponse.SC_NOT_FOUND, + () -> "Aborting test: requesting setting \""+setting.name()+"\" failed with status "+getSetting.getStatusCode()); + } + + // set to new value + Response setSetting = UtilIT.setSetting(setting.name(), setting.value()); + + // assume set or abort + Assumptions.assumeTrue(setSetting.getStatusCode() == HttpServletResponse.SC_OK, + () -> "Aborting test: setting failed for \""+setting.name()+"\" with status "+setSetting.getStatusCode()); + + logger.fine("Set "+setting.name()+" to \""+setting.value()+"\"."); + } + }); + } + + @Override + public void afterTestExecution(ExtensionContext extensionContext) throws Exception { + extensionContext.getTestMethod().ifPresent(method -> { + DBSetting[] settings = method.getAnnotationsByType(DBSetting.class); + for (DBSetting setting : settings) { + // get a stored setting from context + String oldSetting = getStore(extensionContext).remove(setting.name(), String.class); + // if present before, restore + if (oldSetting != null) { + logger.fine("Restoring setting "+setting.name()+" during cleanup to value \""+oldSetting+"\"."); + Response restoreSetting = UtilIT.setSetting(setting.name(), oldSetting); + restoreSetting.then().assertThat().statusCode(HttpServletResponse.SC_OK); + // if NOT present before, delete + } else { + logger.fine("Deleting setting "+setting.name()+" during cleanup."); + Response deleteSetting = UtilIT.deleteSetting(setting.name()); + deleteSetting.then().assertThat().statusCode(HttpServletResponse.SC_OK); + } + } + }); + } +} diff --git a/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettings.java b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettings.java new file mode 100644 index 00000000000..831fe885b31 --- /dev/null +++ b/src/test/java/edu/harvard/iq/dataverse/api/helpers/DBSettings.java @@ -0,0 +1,15 @@ +package edu.harvard.iq.dataverse.api.helpers; + +import org.junit.jupiter.api.extension.ExtendWith; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@ExtendWith(DBSettingExtension.class) +public @interface DBSettings { + DBSetting[] value() default {}; +}