FINERACT-1508: Liquibase test extension for Cucumber + Windows path shortening enabled for Cucumber

This commit is contained in:
Arnold Galovics
2022-03-21 15:09:39 +01:00
committed by Aleksandar Vidakovic
parent 17f521604d
commit 2d2192ca17
6 changed files with 142 additions and 60 deletions
+1
View File
@@ -641,6 +641,7 @@ configure(project.fineractJavaProjects) {
cucumber { cucumber {
tags = 'not @ignore' tags = 'not @ignore'
main = 'io.cucumber.core.cli.Main' main = 'io.cucumber.core.cli.Main'
shorten = "argfile"
} }
// Configuration for spotbugs plugin // Configuration for spotbugs plugin
@@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilde
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -52,6 +53,7 @@ import org.springframework.transaction.support.TransactionTemplate;
@Configuration @Configuration
@EnableJpaAuditing @EnableJpaAuditing
@EnableJpaRepositories(basePackages = "org.apache.fineract.**.domain") @EnableJpaRepositories(basePackages = "org.apache.fineract.**.domain")
@EnableConfigurationProperties(JpaProperties.class)
public class JPAConfig extends JpaBaseConfiguration { public class JPAConfig extends JpaBaseConfiguration {
private final DatabaseTypeResolver databaseTypeResolver; private final DatabaseTypeResolver databaseTypeResolver;
@@ -69,8 +71,8 @@ public class JPAConfig extends JpaBaseConfiguration {
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) { public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder factoryBuilder) {
Map<String, Object> vendorProperties = getVendorProperties(); Map<String, Object> vendorProperties = getVendorProperties();
customizeVendorProperties(vendorProperties); customizeVendorProperties(vendorProperties);
return factoryBuilder.dataSource(getDataSource()).packages(getPackagesToScan()).properties(vendorProperties) return factoryBuilder.dataSource(getDataSource()).properties(vendorProperties).persistenceUnit("jpa-pu")
.persistenceUnit("jpa-pu").packages("org.apache.fineract").jta(false).build(); .packages("org.apache.fineract").jta(false).build();
} }
@Override @Override
@@ -92,6 +92,7 @@ spring.datasource.hikari.dataSourceProperties['maintainTimeStats']=${FINERACT_HI
# TODO FINERACT-890: <prop key="logger">com.mysql.cj.log.Slf4JLogger</prop> # TODO FINERACT-890: <prop key="logger">com.mysql.cj.log.Slf4JLogger</prop>
spring.datasource.hikari.dataSourceProperties['logSlowQueries']=${FINERACT_HIKARI_DS_PROPERTIES_LOG_SLOW_QUERIES:true} spring.datasource.hikari.dataSourceProperties['logSlowQueries']=${FINERACT_HIKARI_DS_PROPERTIES_LOG_SLOW_QUERIES:true}
spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']=${FINERACT_HIKARI_DS_PROPERTIES_DUMP_QUERIES_IN_EXCEPTION:true} spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']=${FINERACT_HIKARI_DS_PROPERTIES_DUMP_QUERIES_IN_EXCEPTION:true}
spring.jpa.open-in-view=false
# Liquibase configuration # Liquibase configuration
spring.liquibase.enabled=true spring.liquibase.enabled=true
@@ -18,8 +18,13 @@
*/ */
package org.apache.fineract.infrastructure.core; package org.apache.fineract.infrastructure.core;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -48,81 +53,121 @@ public class LiquibaseStepDefinitions implements En {
private ExtendedSpringLiquibase initialTenantLiquibase; private ExtendedSpringLiquibase initialTenantLiquibase;
private ExtendedSpringLiquibase tenantLiquibase; private ExtendedSpringLiquibase tenantLiquibase;
private FineractPlatformTenant defaultTenant; private FineractPlatformTenant defaultTenant;
private DataSource defaultTenantDataSource; private DataSource tenantStoreDataSource;
private TenantDatabaseUpgradeService tenantDatabaseUpgradeService; private TenantDatabaseUpgradeService tenantDatabaseUpgradeService;
private List allTenants; private List<FineractPlatformTenant> allTenants;
private SchemaUpgradeNeededException result; private SchemaUpgradeNeededException executionException;
private DataSource defaultTenantDataSource;
public LiquibaseStepDefinitions() { public LiquibaseStepDefinitions() {
Given("Liquibase is disabled with a default tenant", () -> { Given("Liquibase is disabled with a default tenant", () -> {
tenantDataSourceFactory = mock(TenantDataSourceFactory.class); initializeLiquibase(false);
tenantDetailsService = mock(TenantDetailsService.class); });
databaseStateVerifier = mock(TenantDatabaseStateVerifier.class); Given("Liquibase is enabled with a default tenant", () -> {
fineractProperties = mock(FineractProperties.class); initializeLiquibase(true);
liquibaseFactory = mock(ExtendedSpringLiquibaseFactory.class);
defaultTenant = mock(FineractPlatformTenant.class);
allTenants = List.of(defaultTenant);
defaultTenantDataSource = mock(DataSource.class);
initialTenantLiquibase = mock(ExtendedSpringLiquibase.class);
tenantLiquibase = mock(ExtendedSpringLiquibase.class);
initialTenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
tenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
given(databaseStateVerifier.isLiquibaseDisabled()).willReturn(true);
given(fineractProperties.getTenant()).willReturn(new FineractProperties.FineractTenantProperties());
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_store_db", "initial_switch"))
.willReturn(initialTenantStoreLiquibase);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_store_db")).willReturn(tenantStoreLiquibase);
given(tenantDetailsService.findAllTenants()).willReturn(allTenants);
given(tenantDataSourceFactory.create(defaultTenant)).willReturn(defaultTenantDataSource);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "initial_switch")).willReturn(initialTenantLiquibase);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db")).willReturn(tenantLiquibase);
tenantDatabaseUpgradeService = new TenantDatabaseUpgradeService(tenantDetailsService, defaultTenantDataSource,
fineractProperties, databaseStateVerifier, liquibaseFactory, tenantDataSourceFactory);
}); });
Given("Liquibase runs the very first time for the tenant store", () -> { Given("Liquibase runs the very first time for the tenant store", () -> {
given(databaseStateVerifier.isFirstLiquibaseMigration(defaultTenantDataSource)).willReturn(true); given(databaseStateVerifier.isFirstLiquibaseMigration(tenantStoreDataSource)).willReturn(true);
}); });
Given("A previously Flyway migrated tenant store database", () -> { Given("A previously Flyway migrated tenant store database on the latest version", () -> {
given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true); given(databaseStateVerifier.isFlywayPresent(tenantStoreDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(tenantStoreDataSource)).willReturn(true);
}); });
Given("A previously Flyway migrated tenant store database on an earlier version than 1.6", () -> { Given("A previously Flyway migrated tenant store database on an earlier version", () -> {
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(false); given(databaseStateVerifier.isFlywayPresent(tenantStoreDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(tenantStoreDataSource)).willReturn(false);
}); });
Given("Liquibase runs the very first time for the default tenant", () -> { Given("Liquibase runs the very first time for the default tenant", () -> {
given(databaseStateVerifier.isFirstLiquibaseMigration(defaultTenantDataSource)).willReturn(true); given(databaseStateVerifier.isFirstLiquibaseMigration(defaultTenantDataSource)).willReturn(true);
}); });
Given("A previously Flyway migrated default tenant database", () -> { Given("A previously Flyway migrated default tenant database on the latest version", () -> {
given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true); given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(true);
}); });
Given("A previously Flyway migrated default tenant database on the 1.6 version", () -> { Given("A previously Flyway migrated default tenant database on an earlier version", () -> {
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(true); given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(false);
}); });
When("The database migration process is executed", () -> { When("The database migration process is executed", () -> {
// TODO: @galovics will not throw an exception if disabled = true... but if Liquibase is enabled then "Then" try {
// section (as layed out in original tests) will fail tenantDatabaseUpgradeService.afterPropertiesSet();
// this.result = assertThrows(SchemaUpgradeNeededException.class, () -> } catch (SchemaUpgradeNeededException e) {
// tenantDatabaseUpgradeService.afterPropertiesSet()); executionException = e;
}
});
tenantDatabaseUpgradeService.afterPropertiesSet(); Then("The database migration did not do anything", () -> {
verify(databaseStateVerifier).isLiquibaseDisabled();
verifyNoMoreInteractions(databaseStateVerifier);
verifyNoInteractions(tenantDetailsService, tenantStoreDataSource, fineractProperties, liquibaseFactory,
tenantDataSourceFactory);
}); });
Then("The tenant store upgrade fails with a schema upgrade needed", () -> { Then("The tenant store upgrade fails with a schema upgrade needed", () -> {
// TODO: @galovics verifications work dependent on Liquibase enabled or not... for what should we test? assertThat(executionException).isNotNull();
// assertThat(result).isNotNull(); verify(liquibaseFactory).create(eq(tenantStoreDataSource), any());
// verify(liquibaseFactory).create(eq(defaultTenantDataSource), any());
verifyNoMoreInteractions(liquibaseFactory); verifyNoMoreInteractions(liquibaseFactory);
verifyNoInteractions(initialTenantStoreLiquibase, tenantStoreLiquibase, initialTenantLiquibase, tenantLiquibase, verifyNoInteractions(initialTenantStoreLiquibase, tenantStoreLiquibase, initialTenantLiquibase, tenantLiquibase);
defaultTenantDataSource); });
Then("The default tenant upgrade fails with a schema upgrade needed", () -> {
assertThat(executionException).isNotNull();
verify(liquibaseFactory, times(2)).create(eq(tenantStoreDataSource), any());
verify(liquibaseFactory).create(eq(defaultTenantDataSource), any());
verifyNoMoreInteractions(liquibaseFactory);
verify(initialTenantStoreLiquibase).changeLogSync();
verify(tenantStoreLiquibase).afterPropertiesSet();
verifyNoInteractions(initialTenantLiquibase, tenantLiquibase);
});
Then("The tenant store and the default tenant gets upgraded from scratch", () -> {
verify(initialTenantStoreLiquibase).afterPropertiesSet();
verify(tenantStoreLiquibase).afterPropertiesSet();
verify(initialTenantLiquibase).afterPropertiesSet();
verify(tenantLiquibase).afterPropertiesSet();
});
Then("The tenant store and the default tenant gets synced and then upgraded", () -> {
verify(initialTenantStoreLiquibase).changeLogSync();
verify(tenantStoreLiquibase).afterPropertiesSet();
verify(initialTenantLiquibase).changeLogSync();
verify(tenantLiquibase).afterPropertiesSet();
}); });
} }
private void initializeLiquibase(boolean liquibaseEnabled) {
tenantDataSourceFactory = mock(TenantDataSourceFactory.class);
tenantDetailsService = mock(TenantDetailsService.class);
databaseStateVerifier = mock(TenantDatabaseStateVerifier.class);
fineractProperties = mock(FineractProperties.class);
liquibaseFactory = mock(ExtendedSpringLiquibaseFactory.class);
defaultTenant = mock(FineractPlatformTenant.class);
allTenants = List.of(defaultTenant);
tenantStoreDataSource = mock(DataSource.class);
initialTenantLiquibase = mock(ExtendedSpringLiquibase.class);
tenantLiquibase = mock(ExtendedSpringLiquibase.class);
initialTenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
tenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
defaultTenantDataSource = mock(DataSource.class);
given(databaseStateVerifier.isLiquibaseDisabled()).willReturn(!liquibaseEnabled);
given(fineractProperties.getTenant()).willReturn(new FineractProperties.FineractTenantProperties());
given(liquibaseFactory.create(tenantStoreDataSource, "tenant_store_db", "initial_switch")).willReturn(initialTenantStoreLiquibase);
given(liquibaseFactory.create(tenantStoreDataSource, "tenant_store_db")).willReturn(tenantStoreLiquibase);
given(tenantDetailsService.findAllTenants()).willReturn(allTenants);
given(tenantDataSourceFactory.create(defaultTenant)).willReturn(defaultTenantDataSource);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "initial_switch")).willReturn(initialTenantLiquibase);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db")).willReturn(tenantLiquibase);
tenantDatabaseUpgradeService = new TenantDatabaseUpgradeService(tenantDetailsService, tenantStoreDataSource, fineractProperties,
databaseStateVerifier, liquibaseFactory, tenantDataSourceFactory);
}
} }
@@ -77,3 +77,4 @@ spring.datasource.hikari.dataSourceProperties['elideSetAutoCommits']=true
spring.datasource.hikari.dataSourceProperties['maintainTimeStats']=false spring.datasource.hikari.dataSourceProperties['maintainTimeStats']=false
spring.datasource.hikari.dataSourceProperties['logSlowQueries']=true spring.datasource.hikari.dataSourceProperties['logSlowQueries']=true
spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']=true spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']=true
spring.jpa.open-in-view=false
@@ -1,17 +1,49 @@
Feature: Core Infrastructure Feature: Core Infrastructure
@infrastructure @infrastructure
Scenario: Verify that tenant migration service is properly executed Scenario: Verify that schema migration is not executed when set to disabled
Given Liquibase is disabled with a default tenant Given Liquibase is disabled with a default tenant
When The database migration process is executed
Then The database migration did not do anything
@infrastructure
Scenario: Verify that schema migration works from scratch
Given Liquibase is enabled with a default tenant
Given Liquibase runs the very first time for the tenant store Given Liquibase runs the very first time for the tenant store
Given A previously Flyway migrated tenant store database
Given A previously Flyway migrated tenant store database on an earlier version than 1.6
Given Liquibase runs the very first time for the default tenant Given Liquibase runs the very first time for the default tenant
Given A previously Flyway migrated default tenant database When The database migration process is executed
Given A previously Flyway migrated default tenant database on the 1.6 version Then The tenant store and the default tenant gets upgraded from scratch
@infrastructure
Scenario: Verify that schema migration works with the latest Flyway migrated schemas
Given Liquibase is enabled with a default tenant
Given Liquibase runs the very first time for the tenant store
Given A previously Flyway migrated tenant store database on the latest version
Given Liquibase runs the very first time for the default tenant
Given A previously Flyway migrated default tenant database on the latest version
When The database migration process is executed
Then The tenant store and the default tenant gets synced and then upgraded
@infrastructure
Scenario: Verify that schema migration fails when the tenant store is not on the latest Flyway migrated schemas
Given Liquibase is enabled with a default tenant
Given Liquibase runs the very first time for the tenant store
Given A previously Flyway migrated tenant store database on an earlier version
Given Liquibase runs the very first time for the default tenant
Given A previously Flyway migrated default tenant database on the latest version
When The database migration process is executed When The database migration process is executed
Then The tenant store upgrade fails with a schema upgrade needed Then The tenant store upgrade fails with a schema upgrade needed
@infrastructure
Scenario: Verify that schema migration fails when the default tenant is not on the latest Flyway migrated schemas
Given Liquibase is enabled with a default tenant
Given Liquibase runs the very first time for the tenant store
Given A previously Flyway migrated tenant store database on the latest version
Given Liquibase runs the very first time for the default tenant
Given A previously Flyway migrated default tenant database on an earlier version
When The database migration process is executed
Then The default tenant upgrade fails with a schema upgrade needed
@infrastructure @infrastructure
Scenario Outline: Verify empty multi exceptions Scenario Outline: Verify empty multi exceptions
Given A multi exception with exceptions <exception1> and <exception2> Given A multi exception with exceptions <exception1> and <exception2>