pull/9625/merge
Stephane Nicoll 7 years ago
parent 45a24b8705
commit 881d0daff2

@ -18,7 +18,6 @@ package org.springframework.boot.autoconfigure.flyway;
import java.sql.Connection; import java.sql.Connection;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -29,27 +28,21 @@ import org.flywaydb.core.api.MigrationVersion;
import org.flywaydb.core.api.callback.FlywayCallback; import org.flywaydb.core.api.callback.FlywayCallback;
import org.flywaydb.core.internal.callback.SqlScriptFlywayCallback; import org.flywaydb.core.internal.callback.SqlScriptFlywayCallback;
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform; import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InOrder; import org.mockito.InOrder;
import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.SchemaManagement; import org.springframework.boot.jdbc.SchemaManagement;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.core.env.MapPropertySource;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -67,236 +60,217 @@ import static org.mockito.Mockito.mock;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Vedran Pavic * @author Vedran Pavic
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Stephane Nicoll
*/ */
public class FlywayAutoConfigurationTests { public class FlywayAutoConfigurationTests {
@Rule private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
public ExpectedException thrown = ExpectedException.none(); .withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.withPropertyValues("spring.datasource.generate-unique-name=true");
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Before
public void init() {
TestPropertyValues.of("spring.datasource.name:flywaytest").applyTo(this.context);
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test @Test
public void noDataSource() throws Exception { public void noDataSource() {
registerAndRefresh(FlywayAutoConfiguration.class, this.contextRunner.run((context) ->
PropertyPlaceholderAutoConfiguration.class); assertThat(context).doesNotHaveBean(Flyway.class));
assertThat(this.context.getBeanNamesForType(Flyway.class).length).isEqualTo(0);
} }
@Test @Test
public void createDataSource() throws Exception { public void createDataSource() {
TestPropertyValues.of("spring.flyway.url:jdbc:hsqldb:mem:flywaytest", this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
"spring.flyway.user:sa").applyTo(this.context); .withPropertyValues(
registerAndRefresh(EmbeddedDataSourceConfiguration.class, "spring.flyway.url:jdbc:hsqldb:mem:flywaytest",
FlywayAutoConfiguration.class, "spring.flyway.user:sa").run((context) -> {
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); assertThat(context.getBean(Flyway.class).getDataSource()).isNotNull();
assertThat(flyway.getDataSource()).isNotNull(); });
} }
@Test @Test
public void flywayDataSource() throws Exception { public void flywayDataSource() {
registerAndRefresh(FlywayDataSourceConfiguration.class, this.contextRunner.withUserConfiguration(FlywayDataSourceConfiguration.class,
EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, EmbeddedDataSourceConfiguration.class).run((context) -> {
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); assertThat(context.getBean(Flyway.class).getDataSource())
assertThat(flyway.getDataSource()) .isEqualTo(context.getBean("flywayDataSource"));
.isEqualTo(this.context.getBean("flywayDataSource")); });
} }
@Test @Test
public void schemaManagementProviderDetectsDataSource() throws Exception { public void schemaManagementProviderDetectsDataSource() {
registerAndRefresh(FlywayDataSourceConfiguration.class, this.contextRunner.withUserConfiguration(FlywayDataSourceConfiguration.class,
EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, EmbeddedDataSourceConfiguration.class).run((context) -> {
PropertyPlaceholderAutoConfiguration.class); FlywaySchemaManagementProvider schemaManagementProvider = context
FlywaySchemaManagementProvider schemaManagementProvider = this.context .getBean(FlywaySchemaManagementProvider.class);
.getBean(FlywaySchemaManagementProvider.class); assertThat(schemaManagementProvider.getSchemaManagement(context.getBean(
assertThat(schemaManagementProvider DataSource.class))).isEqualTo(SchemaManagement.UNMANAGED);
.getSchemaManagement(this.context.getBean(DataSource.class))) assertThat(schemaManagementProvider.getSchemaManagement(context.getBean(
.isEqualTo(SchemaManagement.UNMANAGED); "flywayDataSource", DataSource.class))).isEqualTo(
assertThat(schemaManagementProvider.getSchemaManagement( SchemaManagement.MANAGED);
this.context.getBean("flywayDataSource", DataSource.class))) });
.isEqualTo(SchemaManagement.MANAGED);
} }
@Test @Test
public void defaultFlyway() throws Exception { public void defaultFlyway() {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, this.contextRunner.withUserConfiguration(
FlywayAutoConfiguration.class, EmbeddedDataSourceConfiguration.class).run((context) -> {
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getLocations()).containsExactly("classpath:db/migration"); assertThat(flyway.getLocations()).containsExactly("classpath:db/migration");
});
} }
@Test @Test
public void overrideLocations() throws Exception { public void overrideLocations() {
TestPropertyValues this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.of("spring.flyway.locations:classpath:db/changelog,classpath:db/migration") .withPropertyValues("spring.flyway.locations:classpath:db/changelog,classpath:db/migration")
.applyTo(this.context); .run((context) -> {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, assertThat(context).hasSingleBean(Flyway.class);
FlywayAutoConfiguration.class, Flyway flyway = context.getBean(Flyway.class);
PropertyPlaceholderAutoConfiguration.class); assertThat(flyway.getLocations()).containsExactly(
Flyway flyway = this.context.getBean(Flyway.class); "classpath:db/changelog", "classpath:db/migration");
assertThat(flyway.getLocations()).containsExactly("classpath:db/changelog", });
"classpath:db/migration");
} }
@Test @Test
public void overrideLocationsList() throws Exception { public void overrideLocationsList() {
TestPropertyValues this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.of("spring.flyway.locations[0]:classpath:db/changelog", .withPropertyValues("spring.flyway.locations[0]:classpath:db/changelog",
"spring.flyway.locations[1]:classpath:db/migration") "spring.flyway.locations[1]:classpath:db/migration")
.applyTo(this.context); .run((context) -> {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, assertThat(context).hasSingleBean(Flyway.class);
FlywayAutoConfiguration.class, Flyway flyway = context.getBean(Flyway.class);
PropertyPlaceholderAutoConfiguration.class); assertThat(flyway.getLocations()).containsExactly(
Flyway flyway = this.context.getBean(Flyway.class); "classpath:db/changelog",
assertThat(flyway.getLocations()).containsExactly("classpath:db/changelog", "classpath:db/migration");
"classpath:db/migration"); });
} }
@Test @Test
public void overrideSchemas() throws Exception { public void overrideSchemas() {
TestPropertyValues.of("spring.flyway.schemas:public").applyTo(this.context); this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
registerAndRefresh(EmbeddedDataSourceConfiguration.class, .withPropertyValues("spring.flyway.schemas:public").run((context) -> {
FlywayAutoConfiguration.class, assertThat(context).hasSingleBean(Flyway.class);
PropertyPlaceholderAutoConfiguration.class); Flyway flyway = context.getBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); assertThat(Arrays.asList(flyway.getSchemas()).toString())
assertThat(Arrays.asList(flyway.getSchemas()).toString()).isEqualTo("[public]"); .isEqualTo("[public]");
});
} }
@Test @Test
public void changeLogDoesNotExist() throws Exception { public void changeLogDoesNotExist() {
TestPropertyValues.of("spring.flyway.locations:file:no-such-dir") this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.applyTo(this.context); .withPropertyValues("spring.flyway.locations:file:no-such-dir")
this.thrown.expect(BeanCreationException.class); .run((context) -> {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, assertThat(context).hasFailed();
FlywayAutoConfiguration.class, assertThat(context).getFailure()
PropertyPlaceholderAutoConfiguration.class); .isInstanceOf(BeanCreationException.class);
});
} }
@Test @Test
public void checkLocationsAllMissing() throws Exception { public void checkLocationsAllMissing() {
TestPropertyValues this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.of("spring.flyway.locations:classpath:db/missing1,classpath:db/migration2", .withPropertyValues(
"spring.flyway.check-location:true") "spring.flyway.locations:classpath:db/missing1,classpath:db/migration2",
.applyTo(this.context); "spring.flyway.check-location:true").run((context) -> {
this.thrown.expect(BeanCreationException.class); assertThat(context).hasFailed();
this.thrown.expectMessage("Cannot find migrations location in"); assertThat(context).getFailure()
registerAndRefresh(EmbeddedDataSourceConfiguration.class, .isInstanceOf(BeanCreationException.class);
FlywayAutoConfiguration.class, assertThat(context).getFailure()
PropertyPlaceholderAutoConfiguration.class); .hasMessageContaining("Cannot find migrations location in");
});
} }
@Test @Test
public void checkLocationsAllExist() throws Exception { public void checkLocationsAllExist() {
TestPropertyValues this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.of("spring.flyway.locations:classpath:db/changelog,classpath:db/migration", .withPropertyValues(
"spring.flyway.check-location:true") "spring.flyway.locations:classpath:db/changelog,classpath:db/migration",
.applyTo(this.context); "spring.flyway.check-location:true").run((context) -> {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, assertThat(context).hasNotFailed();
FlywayAutoConfiguration.class, });
PropertyPlaceholderAutoConfiguration.class);
} }
@Test @Test
public void customFlywayMigrationStrategy() throws Exception { public void customFlywayMigrationStrategy() {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, MockFlywayMigrationStrategy.class).run((context) -> {
MockFlywayMigrationStrategy.class); assertThat(context).hasSingleBean(Flyway.class);
assertThat(this.context.getBean(Flyway.class)).isNotNull(); context.getBean(MockFlywayMigrationStrategy.class).assertCalled();
this.context.getBean(MockFlywayMigrationStrategy.class).assertCalled(); });
} }
@Test @Test
public void customFlywayMigrationInitializer() throws Exception { public void customFlywayMigrationInitializer() throws Exception {
registerAndRefresh(CustomFlywayMigrationInitializer.class, this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, CustomFlywayMigrationInitializer.class).run((context) -> {
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
assertThat(this.context.getBean(Flyway.class)).isNotNull(); FlywayMigrationInitializer initializer = context.getBean(
FlywayMigrationInitializer initializer = this.context FlywayMigrationInitializer.class);
.getBean(FlywayMigrationInitializer.class); assertThat(initializer.getOrder()).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
assertThat(initializer.getOrder()).isEqualTo(Ordered.HIGHEST_PRECEDENCE); });
} }
@Test @Test
public void customFlywayWithJpa() throws Exception { public void customFlywayWithJpa() {
registerAndRefresh(CustomFlywayWithJpaConfiguration.class, this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
EmbeddedDataSourceConfiguration.class, FlywayAutoConfiguration.class, CustomFlywayWithJpaConfiguration.class).run((context) ->
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasNotFailed());
} }
@Test @Test
public void overrideBaselineVersionString() throws Exception { public void overrideBaselineVersionString() {
TestPropertyValues.of("spring.flyway.baseline-version=0").applyTo(this.context); this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
registerAndRefresh(EmbeddedDataSourceConfiguration.class, .withPropertyValues("spring.flyway.baseline-version=0")
FlywayAutoConfiguration.class, .run((context) -> {
PropertyPlaceholderAutoConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); Flyway flyway = context.getBean(Flyway.class);
assertThat(flyway.getBaselineVersion()) assertThat(flyway.getBaselineVersion())
.isEqualTo(MigrationVersion.fromVersion("0")); .isEqualTo(MigrationVersion.fromVersion("0"));
});
} }
@Test @Test
public void overrideBaselineVersionNumber() throws Exception { public void overrideBaselineVersionNumber() {
Map<String, Object> source = Collections this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.<String, Object>singletonMap("spring.flyway.baseline-version", 1); .withPropertyValues("spring.flyway.baseline-version=1")
this.context.getEnvironment().getPropertySources() .run((context) -> {
.addLast(new MapPropertySource("flyway", source)); assertThat(context).hasSingleBean(Flyway.class);
registerAndRefresh(EmbeddedDataSourceConfiguration.class, Flyway flyway = context.getBean(Flyway.class);
FlywayAutoConfiguration.class, assertThat(flyway.getBaselineVersion())
PropertyPlaceholderAutoConfiguration.class); .isEqualTo(MigrationVersion.fromVersion("1"));
Flyway flyway = this.context.getBean(Flyway.class); });
assertThat(flyway.getBaselineVersion())
.isEqualTo(MigrationVersion.fromVersion("1"));
} }
@Test @Test
public void useVendorDirectory() throws Exception { public void useVendorDirectory() {
TestPropertyValues this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.of("spring.flyway.locations=classpath:db/vendors/{vendor},classpath:db/changelog") .withPropertyValues("spring.flyway.locations=classpath:db/vendors/{vendor},classpath:db/changelog")
.applyTo(this.context); .run((context) -> {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, assertThat(context).hasSingleBean(Flyway.class);
FlywayAutoConfiguration.class, Flyway flyway = context.getBean(Flyway.class);
PropertyPlaceholderAutoConfiguration.class); assertThat(flyway.getLocations()).containsExactlyInAnyOrder(
Flyway flyway = this.context.getBean(Flyway.class); "classpath:db/vendors/h2", "classpath:db/changelog");
assertThat(flyway.getLocations()).containsExactlyInAnyOrder( });
"classpath:db/vendors/h2", "classpath:db/changelog");
} }
@Test @Test
public void callbacksAreConfiguredAndOrdered() throws Exception { public void callbacksAreConfiguredAndOrdered() {
registerAndRefresh(EmbeddedDataSourceConfiguration.class, this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
FlywayAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, CallbackConfiguration.class).run((context) -> {
CallbackConfiguration.class); assertThat(context).hasSingleBean(Flyway.class);
assertThat(this.context.getBeansOfType(Flyway.class)).hasSize(1); Flyway flyway = context.getBean(Flyway.class);
Flyway flyway = this.context.getBean(Flyway.class); FlywayCallback callbackOne = context.getBean("callbackOne",
FlywayCallback callbackOne = this.context.getBean("callbackOne", FlywayCallback.class);
FlywayCallback.class); FlywayCallback callbackTwo = context.getBean("callbackTwo",
FlywayCallback callbackTwo = this.context.getBean("callbackTwo", FlywayCallback.class);
FlywayCallback.class); assertThat(flyway.getCallbacks()).hasSize(3);
assertThat(flyway.getCallbacks()).hasSize(3); assertThat(flyway.getCallbacks()).startsWith(callbackTwo, callbackOne);
assertThat(flyway.getCallbacks()).startsWith(callbackTwo, callbackOne); assertThat(flyway.getCallbacks()[2]).isInstanceOf(SqlScriptFlywayCallback.class);
assertThat(flyway.getCallbacks()[2]).isInstanceOf(SqlScriptFlywayCallback.class); InOrder orderedCallbacks = inOrder(callbackOne, callbackTwo);
InOrder orderedCallbacks = inOrder(callbackOne, callbackTwo); orderedCallbacks.verify(callbackTwo).beforeMigrate(any(Connection.class));
orderedCallbacks.verify(callbackTwo).beforeMigrate(any(Connection.class)); orderedCallbacks.verify(callbackOne).beforeMigrate(any(Connection.class));
orderedCallbacks.verify(callbackOne).beforeMigrate(any(Connection.class)); });
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
this.context.register(annotatedClasses);
this.context.refresh();
} }
@Configuration @Configuration

Loading…
Cancel
Save