pull/10466/head
Stephane Nicoll 7 years ago
parent 0ea7d22870
commit 76606afe86

@ -24,23 +24,17 @@ import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.test.City;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
@ -51,8 +45,6 @@ import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
@ -65,172 +57,154 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public abstract class AbstractJpaAutoConfigurationTests {
@Rule
public ExpectedException expected = ExpectedException.none();
private final Class<?> autoConfiguredClass;
protected AnnotationConfigApplicationContext context;
private final ApplicationContextRunner contextRunner;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
protected AbstractJpaAutoConfigurationTests(Class<?> autoConfiguredClass) {
this.autoConfiguredClass = autoConfiguredClass;
this.contextRunner = new ApplicationContextRunner()
.withPropertyValues("spring.datasource.generate-unique-name=true")
.withUserConfiguration(TestConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
TransactionAutoConfiguration.class, autoConfiguredClass));
}
protected abstract Class<?> getAutoConfigureClass();
protected ApplicationContextRunner contextRunner() {
return this.contextRunner;
}
@Test
public void testNoDataSource() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(PropertyPlaceholderAutoConfiguration.class,
getAutoConfigureClass());
this.expected.expect(BeanCreationException.class);
this.expected.expectMessage("No qualifying bean");
this.expected.expectMessage("DataSource");
context.refresh();
context.close();
public void dataSourceIsNotAvailable() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(
this.autoConfiguredClass)).run((context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure())
.isInstanceOf(BeanCreationException.class);
assertThat(context.getStartupFailure())
.hasMessageContaining("No qualifying bean");
assertThat(context.getStartupFailure()).hasMessageContaining("DataSource");
});
}
@Test
public void testEntityManagerCreated() throws Exception {
load();
assertThat(this.context.getBean(DataSource.class)).isNotNull();
assertThat(this.context.getBean(JpaTransactionManager.class)).isNotNull();
public void dataSourceIsCreatedWithDefaultConfig() {
this.contextRunner.run((context) -> {
assertThat(context).hasSingleBean(DataSource.class);
assertThat(context).hasSingleBean(JpaTransactionManager.class);
});
}
@Test
public void testDataSourceTransactionManagerNotCreated() throws Exception {
load(new Class<?>[0],
new Class<?>[] { DataSourceTransactionManagerAutoConfiguration.class });
assertThat(this.context.getBean(DataSource.class)).isNotNull();
assertThat(this.context.getBean("transactionManager"))
.isInstanceOf(JpaTransactionManager.class);
public void jtaTransactionManagerTakesPrecedence() {
this.contextRunner.withConfiguration(AutoConfigurations.of(
DataSourceTransactionManagerAutoConfiguration.class)).run((context) -> {
assertThat(context).hasSingleBean(DataSource.class);
assertThat(context).hasSingleBean(JpaTransactionManager.class);
assertThat(context).getBean("transactionManager")
.isInstanceOf(JpaTransactionManager.class);
});
}
@Test
public void testOpenEntityManagerInViewInterceptorCreated() throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestConfiguration.class, EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
context.refresh();
assertThat(context.getBean(OpenEntityManagerInViewInterceptor.class)).isNotNull();
context.close();
public void openEntityManagerInViewInterceptorIsCreated() {
new WebApplicationContextRunner()
.withPropertyValues("spring.datasource.generate-unique-name=true")
.withUserConfiguration(TestConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
TransactionAutoConfiguration.class, this.autoConfiguredClass))
.run((context) -> assertThat(context)
.hasSingleBean(OpenEntityManagerInViewInterceptor.class));
}
@Test
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenFilterPresent()
throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(TestFilterConfiguration.class,
EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
context.refresh();
assertThat(getInterceptorBeans(context).length).isEqualTo(0);
context.close();
public void openEntityManagerInViewInterceptorIsNotRegisteredWhenFilterPresent() {
new WebApplicationContextRunner()
.withPropertyValues("spring.datasource.generate-unique-name=true")
.withUserConfiguration(TestFilterConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
TransactionAutoConfiguration.class, this.autoConfiguredClass))
.run((context) -> assertThat(context)
.doesNotHaveBean(OpenEntityManagerInViewInterceptor.class));
}
@Test
public void testOpenEntityManagerInViewInterceptorNotRegisteredWhenExplicitlyOff()
throws Exception {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
TestPropertyValues.of("spring.jpa.open_in_view:false").applyTo(context);
context.register(TestConfiguration.class, EmbeddedDataSourceConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
ConfigurationPropertySources.attach(context.getEnvironment());
context.refresh();
assertThat(getInterceptorBeans(context).length).isEqualTo(0);
context.close();
public void openEntityManagerInViewInterceptorISNotRegisteredWhenExplicitlyOff() {
new WebApplicationContextRunner()
.withPropertyValues(
"spring.datasource.generate-unique-name=true",
"spring.jpa.open-in-view=false")
.withUserConfiguration(TestConfiguration.class)
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
TransactionAutoConfiguration.class, this.autoConfiguredClass))
.run((context) -> assertThat(context)
.doesNotHaveBean(OpenEntityManagerInViewInterceptor.class));
}
@Test
public void customJpaProperties() throws Exception {
load("spring.jpa.properties.a:b", "spring.jpa.properties.a.b:c",
"spring.jpa.properties.c:d");
LocalContainerEntityManagerFactoryBean bean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = bean.getJpaPropertyMap();
assertThat(map.get("a")).isEqualTo("b");
assertThat(map.get("c")).isEqualTo("d");
assertThat(map.get("a.b")).isEqualTo("c");
public void customJpaProperties() {
this.contextRunner.withPropertyValues("spring.jpa.properties.a:b",
"spring.jpa.properties.a.b:c",
"spring.jpa.properties.c:d").run((context) -> {
LocalContainerEntityManagerFactoryBean bean = context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = bean.getJpaPropertyMap();
assertThat(map.get("a")).isEqualTo("b");
assertThat(map.get("c")).isEqualTo("d");
assertThat(map.get("a.b")).isEqualTo("c");
});
}
@Test
public void usesManuallyDefinedLocalContainerEntityManagerFactoryBeanIfAvailable() {
load(TestConfigurationWithLocalContainerEntityManagerFactoryBean.class);
LocalContainerEntityManagerFactoryBean factoryBean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = factoryBean.getJpaPropertyMap();
assertThat(map.get("configured")).isEqualTo("manually");
this.contextRunner.withUserConfiguration(
TestConfigurationWithLocalContainerEntityManagerFactoryBean.class
).run((context) -> {
LocalContainerEntityManagerFactoryBean factoryBean = context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Map<String, Object> map = factoryBean.getJpaPropertyMap();
assertThat(map.get("configured")).isEqualTo("manually");
});
}
@Test
public void usesManuallyDefinedEntityManagerFactoryIfAvailable() {
load(TestConfigurationWithLocalContainerEntityManagerFactoryBean.class);
EntityManagerFactory factoryBean = this.context
.getBean(EntityManagerFactory.class);
Map<String, Object> map = factoryBean.getProperties();
assertThat(map.get("configured")).isEqualTo("manually");
this.contextRunner.withUserConfiguration(
TestConfigurationWithLocalContainerEntityManagerFactoryBean.class
).run((context) -> {
EntityManagerFactory factoryBean = context
.getBean(EntityManagerFactory.class);
Map<String, Object> map = factoryBean.getProperties();
assertThat(map.get("configured")).isEqualTo("manually");
});
}
@Test
public void usesManuallyDefinedTransactionManagerBeanIfAvailable() {
load(TestConfigurationWithTransactionManager.class);
PlatformTransactionManager txManager = this.context
.getBean(PlatformTransactionManager.class);
assertThat(txManager).isInstanceOf(CustomJpaTransactionManager.class);
this.contextRunner.withUserConfiguration(
TestConfigurationWithTransactionManager.class
).run((context) -> {
PlatformTransactionManager txManager = context
.getBean(PlatformTransactionManager.class);
assertThat(txManager).isInstanceOf(CustomJpaTransactionManager.class);
});
}
@Test
public void customPersistenceUnitManager() throws Exception {
load(TestConfigurationWithCustomPersistenceUnitManager.class);
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Field field = LocalContainerEntityManagerFactoryBean.class
.getDeclaredField("persistenceUnitManager");
field.setAccessible(true);
assertThat(field.get(entityManagerFactoryBean))
.isEqualTo(this.context.getBean(PersistenceUnitManager.class));
}
protected void load(String... environment) {
load(new Class<?>[0], new Class<?>[0], environment);
}
protected void load(Class<?> config, String... environment) {
Class<?>[] configs = config != null ? new Class<?>[] { config } : null;
load(configs, new Class<?>[0], environment);
}
protected void load(Class<?>[] configs, Class<?>[] autoConfigs,
String... environment) {
load(configs, autoConfigs, null, environment);
public void customPersistenceUnitManager() {
this.contextRunner.withUserConfiguration(
TestConfigurationWithCustomPersistenceUnitManager.class
).run((context) -> {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = context
.getBean(LocalContainerEntityManagerFactoryBean.class);
Field field = LocalContainerEntityManagerFactoryBean.class
.getDeclaredField("persistenceUnitManager");
field.setAccessible(true);
assertThat(field.get(entityManagerFactoryBean))
.isEqualTo(context.getBean(PersistenceUnitManager.class));
});
}
protected void load(Class<?>[] configs, Class<?>[] autoConfigs,
ClassLoader classLoader, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
if (classLoader != null) {
ctx.setClassLoader(classLoader);
}
TestPropertyValues.of(environment)
.and("spring.datasource.generate-unique-name=true").applyTo(ctx);
ctx.register(TestConfiguration.class);
if (!ObjectUtils.isEmpty(configs)) {
ctx.register(configs);
}
ctx.register(DataSourceAutoConfiguration.class,
TransactionAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, getAutoConfigureClass());
if (!ObjectUtils.isEmpty(autoConfigs)) {
ctx.register(autoConfigs);
}
ctx.refresh();
this.context = ctx;
}
private String[] getInterceptorBeans(ApplicationContext context) {
return context.getBeanNamesForType(OpenEntityManagerInViewInterceptor.class);
}
@Configuration
@TestAutoConfigurationPackage(City.class)

@ -34,12 +34,11 @@ import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
@ -65,95 +64,113 @@ import static org.mockito.Mockito.mock;
public class HibernateJpaAutoConfigurationTests
extends AbstractJpaAutoConfigurationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Override
protected Class<?> getAutoConfigureClass() {
return HibernateJpaAutoConfiguration.class;
public HibernateJpaAutoConfigurationTests() {
super(HibernateJpaAutoConfiguration.class);
}
@Test
public void testDataScriptWithMissingDdl() throws Exception {
this.thrown.expectMessage("ddl.sql");
this.thrown.expectMessage("spring.datasource.schema");
load("spring.datasource.data:classpath:/city.sql",
public void testDataScriptWithMissingDdl() {
contextRunner().withPropertyValues(
"spring.datasource.data:classpath:/city.sql",
// Missing:
"spring.datasource.schema:classpath:/ddl.sql");
"spring.datasource.schema:classpath:/ddl.sql").run((context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure()).hasMessageContaining("ddl.sql");
assertThat(context.getStartupFailure())
.hasMessageContaining("spring.datasource.schema");
});
}
@Test
public void testDataScript() throws Exception {
public void testDataScript() {
// This can't succeed because the data SQL is executed immediately after the
// schema
// and Hibernate hasn't initialized yet at that point
this.thrown.expect(BeanCreationException.class);
load("spring.datasource.data:classpath:/city.sql");
contextRunner().withPropertyValues(
"spring.datasource.data:classpath:/city.sql").run((context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure())
.isInstanceOf(BeanCreationException.class);
});
}
@Test
public void testDataScriptRunsEarly() {
load(new Class<?>[] { TestInitializedJpaConfiguration.class }, null,
new HideDataScriptClassLoader(), "spring.jpa.show-sql=true",
"spring.jpa.hibernate.ddl-auto:create-drop",
"spring.datasource.data:classpath:/city.sql");
assertThat(this.context.getBean(TestInitializedJpaConfiguration.class).called)
.isTrue();
contextRunner().withUserConfiguration(TestInitializedJpaConfiguration.class)
.withClassLoader(new HideDataScriptClassLoader())
.withPropertyValues("spring.jpa.show-sql=true",
"spring.jpa.hibernate.ddl-auto:create-drop",
"spring.datasource.data:classpath:/city.sql").run((context) ->
assertThat(context.getBean(TestInitializedJpaConfiguration.class).called)
.isTrue());
}
@Test
public void testFlywaySwitchOffDdlAuto() throws Exception {
load(new Class<?>[0], new Class<?>[] { FlywayAutoConfiguration.class },
"spring.datasource.initialize:false",
"spring.flyway.locations:classpath:db/city");
public void testFlywaySwitchOffDdlAuto() {
contextRunner()
.withPropertyValues("spring.datasource.initialize:false",
"spring.flyway.locations:classpath:db/city")
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.run(context -> assertThat(context).hasNotFailed());
}
@Test
public void testFlywayPlusValidation() throws Exception {
load(new Class<?>[0], new Class<?>[] { FlywayAutoConfiguration.class },
"spring.datasource.initialize:false",
"spring.flyway.locations:classpath:db/city",
"spring.jpa.hibernate.ddl-auto:validate");
public void testFlywayPlusValidation() {
contextRunner()
.withPropertyValues("spring.datasource.initialize:false",
"spring.flyway.locations:classpath:db/city",
"spring.jpa.hibernate.ddl-auto:validate")
.withConfiguration(AutoConfigurations.of(FlywayAutoConfiguration.class))
.run(context -> assertThat(context).hasNotFailed());
}
@Test
public void testLiquibasePlusValidation() throws Exception {
load(new Class<?>[0], new Class<?>[] { LiquibaseAutoConfiguration.class },
"spring.datasource.initialize:false",
"spring.liquibase.changeLog:classpath:db/changelog/db.changelog-city.yaml",
"spring.jpa.hibernate.ddl-auto:validate");
public void testLiquibasePlusValidation() {
contextRunner()
.withPropertyValues("spring.datasource.initialize:false",
"spring.liquibase.changeLog:classpath:db/changelog/db.changelog-city.yaml",
"spring.jpa.hibernate.ddl-auto:validate")
.withConfiguration(AutoConfigurations.of(LiquibaseAutoConfiguration.class))
.run(context -> assertThat(context).hasNotFailed());
}
@Test
public void defaultJtaPlatform() throws Exception {
load(JtaAutoConfiguration.class);
Map<String, Object> jpaPropertyMap = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat(jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isInstanceOf(SpringJtaPlatform.class);
public void jtaDefaultPlatform() {
contextRunner().withConfiguration(AutoConfigurations.of(
JtaAutoConfiguration.class)).run((context) -> {
Map<String, Object> jpaPropertyMap = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat(jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isInstanceOf(SpringJtaPlatform.class);
});
}
@Test
public void testCustomJtaPlatform() throws Exception {
load(JtaAutoConfiguration.class,
"spring.jpa.properties.hibernate.transaction.jta.platform:"
+ TestJtaPlatform.class.getName());
Map<String, Object> jpaPropertyMap = this.context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat((String) jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isEqualTo(TestJtaPlatform.class.getName());
public void jtaCustomPlatform() {
contextRunner()
.withPropertyValues(
"spring.jpa.properties.hibernate.transaction.jta.platform:"
+ TestJtaPlatform.class.getName())
.withConfiguration(AutoConfigurations.of(
JtaAutoConfiguration.class)).run((context) -> {
Map<String, Object> jpaPropertyMap = context
.getBean(LocalContainerEntityManagerFactoryBean.class)
.getJpaPropertyMap();
assertThat((String) jpaPropertyMap.get("hibernate.transaction.jta.platform"))
.isEqualTo(TestJtaPlatform.class.getName());
});
}
@Test
public void testCustomJpaTransactionManagerUsingProperties() throws Exception {
load("spring.transaction.default-timeout:30",
"spring.transaction.rollback-on-commit-failure:true");
JpaTransactionManager transactionManager = this.context
.getBean(JpaTransactionManager.class);
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
public void jtaCustomTransactionManagerUsingProperties() {
contextRunner().withPropertyValues("spring.transaction.default-timeout:30",
"spring.transaction.rollback-on-commit-failure:true").run((context) -> {
JpaTransactionManager transactionManager = context
.getBean(JpaTransactionManager.class);
assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30);
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
});
}
@Configuration

Loading…
Cancel
Save