All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kiwiproject.test.dropwizard.app.PostgresAppTestExtension Maven / Gradle / Ivy

package org.kiwiproject.test.dropwizard.app;

import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.testing.ConfigOverride;
import io.dropwizard.testing.ResourceHelpers;
import io.dropwizard.testing.junit5.DropwizardAppExtension;
import io.zonky.test.db.postgres.embedded.LiquibasePreparer;
import io.zonky.test.db.postgres.junit5.EmbeddedPostgresExtension;
import io.zonky.test.db.postgres.junit5.PreparedDbExtension;
import lombok.Getter;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.postgresql.Driver;

/**
 * Multipurpose extension for Dropwizard {@link Application} testing requiring a PostgreSQL database. The extension
 * will spin up an embedded PostgreSQL database instance, run the migrations and then configure the
 * {@link DropwizardAppExtension} with the database information.
 * 

* There are several things to note when using this extension: *

    *
  • * The embedded PostgreSQL extension supports both Flyway and Liquibase, but we are only supporting Liquibase * currently. *
  • *
  • * The application's {@link Configuration} class must have a Dropwizard * {@link io.dropwizard.db.DataSourceFactory DataSourceFactory}. By default the property name is expected to * be "database", i.e. the property will either have {@code @JsonProperty("database")} or be named "database", * but you can change this using the alternate constructor. *
  • *
  • * The YAML configuration file provided to this extension can contain a * {@link io.dropwizard.db.DataSourceFactory DataSourceFactory} property with custom values, but this extension * always overrides the following properties: {@code driverClass}, {@code user}, and {@code url} because the * driver is always Postgres, and the user and url are provided by the embedded Postgres database. *
  • *
  • * You should not register {@code DropwizardExtensionsSupport} or the embedded Postgres * extension. See the WARNING below. *
  • *
*

* To include this extension in an Application test, add the following at the top of the class: *

 * {@literal @}RegisterExtension
 *  public static PostgresAppTestExtension<AppConfiguration> POSTGRES_APP =
 *      new PostgresAppTestExtension("migrations.xml", "config.yml", App.class);
 * 
* Here is a one of the simplest {@code config.yml} files you can have: *
 * ---
 * server:
 *  type: simple
 * 
* Note that you do not need to declare a database property because this extension overrides the * required properties. But, you can add other custom properties to the configuration if desired: *
 * ---
 * server:
 *  type: simple
 *
 * database:
 *   initialSize: 1
 *   minSize: 1
 *   maxSize: 5
 * 
*

* Most of the time these won't really matter in unit/integration testing scenarios. Next is a fragment of a sample * Configuration class that uses the default property name: *

 * {@literal @}JsonProperty("database")
 *  private DataSourceFactory dataSourceFactory = new DataSourceFactory();
 * 
* The extension assumes the configuration uses {@code "database"} as the name of the DataSourceFactory property, as * shown in the above examples which specify the name via the {@code JsonProperty} annotation. If the property in * your configuration is named something else, you can use the alternate constructor which accepts a custom property * name. For example: *
 *  // Uses "db" as the name of the DataSourceFactory in the configuration
 * {@literal @}RegisterExtension
 *  public static PostgresAppTestExtension<AppConfiguration> POSTGRES_APP =
 *      new PostgresAppTestExtension("migrations.xml", "config.yml", App.class, "db");
 * 
*

* The test extension instance can access the application and the PostgreSQL instance by calling * {@code POSTGRES_APP.getApp()} and {@code POSTGRES_APP.getPostgres()} respectively. *

* You can also provide one or more {@link ConfigOverride} values to the extension: *

 * {@literal @}RegisterExtension
 *  public static PostgresAppTestExtension<AppConfiguration> POSTGRES_APP =
 *      new PostgresAppTestExtension("migrations.xml", "config.yml", App.class,
 *          ConfigOverride.config("someValue", "42"),
 *          ConfigOverride.config("aLazyValue", () -> calculateTheLazyValue()));
 * 
*

* WARNING: When using this extension you should not register * {@code DropwizardExtensionsSupport} or the embedded Postgres extension since this extension programmatically * registers both of them. Doing so will almost certainly result in unexpected behavior such as * {@code NullPointerException}s being thrown. *

* For information on how the embedded PostgreSQL extension works see: * https://github.com/zonkyio/embedded-postgres *
* For information on how the dropwizard app extension works see: * https://www.dropwizard.io/en/latest/manual/testing.html#junit-5 * * @param the {@link Configuration} implementation for the application */ @Getter public class PostgresAppTestExtension implements BeforeAllCallback, AfterAllCallback { private static final String DEFAULT_DATASOURCE_FACTORY_PROPERTY = "database"; private final PreparedDbExtension postgres; private final DropwizardAppExtension app; /** * Create a new instance using the default property name ("database") for the DataSourceFactory. * * @param migrationClasspathLocation the classpath location of the Liquibase migrations file to use * @param configFileName the name of the classpath resource to use as the application configuration file * @param appClass the Dropwizard application class * @param configOverrides optional configuration override values */ public PostgresAppTestExtension(String migrationClasspathLocation, String configFileName, Class> appClass, ConfigOverride... configOverrides) { this(migrationClasspathLocation, configFileName, appClass, DEFAULT_DATASOURCE_FACTORY_PROPERTY, configOverrides); } /** * Create a new instance with a custom property name for the DataSourceFactory. * * @param migrationClasspathLocation the classpath location of the Liquibase migrations file to use * @param configFileName the name of the classpath resource to use as the application * configuration file * @param appClass the Dropwizard application class * @param dataSourceFactoryPropertyName the name of the DataSourceFactory property in the Configuration class, * i.e. what is specified in the YAML configuration * @param configOverrides optional configuration override values */ public PostgresAppTestExtension(String migrationClasspathLocation, String configFileName, Class> appClass, String dataSourceFactoryPropertyName, ConfigOverride... configOverrides) { var liquibasePreparer = LiquibasePreparer.forClasspathLocation(migrationClasspathLocation); postgres = EmbeddedPostgresExtension.preparedDatabase(liquibasePreparer); var dbUserProperty = dataSourceFactoryPropertyName + ".user"; var dbUrlProperty = dataSourceFactoryPropertyName + ".url"; var dbDriverClassProperty = dataSourceFactoryPropertyName + ".driverClass"; var userConfigOverride = ConfigOverride.config(dbUserProperty, () -> postgres.getConnectionInfo().getUser()); var urlConfigOverride = ConfigOverride.config(dbUrlProperty, () -> "jdbc:postgresql://localhost:" + postgres.getConnectionInfo().getPort() + "/" + postgres.getConnectionInfo().getDbName()); var driverConfigOverride = ConfigOverride.config(dbDriverClassProperty, Driver.class.getName()); var postgresConfigOverrides = new ConfigOverride[]{userConfigOverride, urlConfigOverride, driverConfigOverride}; var combinedConfigOverrides = ArrayUtils.addAll(postgresConfigOverrides, configOverrides); app = new DropwizardAppExtension<>( appClass, ResourceHelpers.resourceFilePath(configFileName), combinedConfigOverrides); } @Override public void beforeAll(ExtensionContext extensionContext) throws Exception { postgres.beforeAll(extensionContext); app.before(); } @Override public void afterAll(ExtensionContext extensionContext) { app.after(); postgres.afterAll(extensionContext); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy