/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.liquibase;
import java.io.File;
import java.util.Map;
import javax.sql.DataSource;
import liquibase.integration.spring.SpringLiquibase;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.liquibase.CommonsLoggingLiquibaseLogger;
import org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LiquibaseAutoConfiguration}.
*
* @author Marcel Overdijk
* @author EddĂș MelĂ©ndez
* @author Andy Wilkinson
*/
public class LiquibaseAutoConfigurationTests {
@Rule
public ExpectedException expected = ExpectedException.none();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Rule
public OutputCapture outputCapture = new OutputCapture();
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@Before
public void init() {
EnvironmentTestUtils.addEnvironment(this.context,
"spring.datasource.name:liquibasetest");
new LiquibaseServiceLocatorApplicationListener().onApplicationEvent(null);
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void testNoDataSource() throws Exception {
this.context.register(LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(SpringLiquibase.class).length)
.isEqualTo(0);
}
@Test
public void testDefaultSpringLiquibase() throws Exception {
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getChangeLog())
.isEqualTo("classpath:/db/changelog/db.changelog-master.yaml");
assertThat(liquibase.getContexts()).isNull();
assertThat(liquibase.getDefaultSchema()).isNull();
assertThat(liquibase.isDropFirst()).isFalse();
}
@Test
public void testXmlChangeLog() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.change-log:classpath:/db/changelog/db.changelog-override.xml");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getChangeLog())
.isEqualTo("classpath:/db/changelog/db.changelog-override.xml");
}
@Test
public void testJsonChangeLog() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.change-log:classpath:/db/changelog/db.changelog-override.json");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getChangeLog())
.isEqualTo("classpath:/db/changelog/db.changelog-override.json");
}
@Test
public void testSqlChangeLog() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.change-log:classpath:/db/changelog/db.changelog-override.sql");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getChangeLog())
.isEqualTo("classpath:/db/changelog/db.changelog-override.sql");
}
@Test
public void testOverrideContexts() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.contexts:test, production");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getContexts()).isEqualTo("test, production");
}
@Test
public void testOverrideDefaultSchema() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.default-schema:public");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getDefaultSchema()).isEqualTo("public");
}
@Test
public void testOverrideDropFirst() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context, "liquibase.drop-first:true");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.isDropFirst()).isTrue();
}
@Test
public void testOverrideDataSource() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.url:jdbc:hsqldb:mem:liquibase", "liquibase.user:sa");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getDataSource().getConnection().getMetaData().getURL())
.isEqualTo("jdbc:hsqldb:mem:liquibase");
}
@Test(expected = BeanCreationException.class)
public void testChangeLogDoesNotExist() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.change-log:classpath:/no-such-changelog.yaml");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
}
@Test
public void testLogger() throws Exception {
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
Object log = ReflectionTestUtils.getField(liquibase, "log");
assertThat(log).isInstanceOf(CommonsLoggingLiquibaseLogger.class);
assertThat(this.outputCapture.toString()).doesNotContain(": liquibase:");
}
@Test
public void testOverrideLabels() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.labels:test, production");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getLabels()).isEqualTo("test, production");
}
@Test
@SuppressWarnings("unchecked")
public void testOverrideParameters() throws Exception {
EnvironmentTestUtils.addEnvironment(this.context, "liquibase.parameters.foo:bar");
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
Map<String, String> parameters = (Map<String, String>) ReflectionTestUtils
.getField(liquibase, "parameters");
assertThat(parameters.containsKey("foo")).isTrue();
assertThat(parameters.get("foo")).isEqualTo("bar");
}
@Test
public void testRollbackFile() throws Exception {
File file = this.temp.newFile("rollback-file.sql");
EnvironmentTestUtils.addEnvironment(this.context,
"liquibase.rollbackFile:" + file.getAbsolutePath());
this.context.register(EmbeddedDataSourceConfiguration.class,
LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
File actualFile = (File) ReflectionTestUtils.getField(liquibase, "rollbackFile");
assertThat(actualFile).isEqualTo(file).exists();
String content = new String(FileCopyUtils.copyToByteArray(file));
assertThat(content).contains("DROP TABLE PUBLIC.customer;");
}
@Test
public void testLiquibaseDataSource() {
this.context.register(LiquibaseDataSourceConfiguration.class,
EmbeddedDataSourceConfiguration.class, LiquibaseAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
SpringLiquibase liquibase = this.context.getBean(SpringLiquibase.class);
assertThat(liquibase.getDataSource())
.isEqualTo(this.context.getBean("liquibaseDataSource"));
}
@Configuration
static class LiquibaseDataSourceConfiguration {
@Bean
@Primary
public DataSource normalDataSource() {
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:normal").username("sa")
.build();
}
@LiquibaseDataSource
@Bean
public DataSource liquibaseDataSource() {
return DataSourceBuilder.create().url("jdbc:hsqldb:mem:liquibasetest")
.username("sa").build();
}
}
}