Commit 81d56355 authored by Phillip Webb's avatar Phillip Webb

Add @DataJpaTest annotation

Add @DataJpaTest and @AutoConfigureTestDatabase annotations to allow
testing of an application "slice" that only deals JPA.

See gh-4901
parent bbc91cc0
......@@ -34,6 +34,11 @@
<artifactId>javax.servlet-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
......@@ -45,12 +50,28 @@
<version>2.19</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<exclusions>
<exclusion>
<groupId>org.jboss.spec.javax.transaction</groupId>
<artifactId>jboss-transaction-api_1.2_spec</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-htmlunit-driver</artifactId>
<version>2.52.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
......@@ -66,6 +87,17 @@
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</exclusion>
</exclusions>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.aspectj</groupId>
......@@ -77,6 +109,16 @@
<artifactId>aspectjweaver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
......
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.test.autoconfigure.properties.PropertyMapping;
/**
* Annotation that can be applied to a test class to configure a test database to use
* instead of any application defined or auto-configured {@link DataSource}.
*
* @author Phillip Webb
* @see TestDatabaseAutoConfiguration
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ImportAutoConfiguration(TestDatabaseAutoConfiguration.class)
@PropertyMapping("spring.test.database")
public @interface AutoConfigureTestDatabase {
/**
* If the test database should replace any existing.
*/
Replace replace() default Replace.ANY;
/**
* The type of connection to be establish when {@link #replace() replacing} the data
* source. By default will attempt to detect the connection based on the classpath.
*/
EmbeddedDatabaseConnection connection() default EmbeddedDatabaseConnection.NONE;
/**
* What the test database can replace.
*/
enum Replace {
/**
* Replace any DataSource bean (auto-configured or manually defined).
*/
ANY,
/**
* Only replace auto-configured DataSource.
*/
AUTO_CONFIGURED,
/**
* Don't replace the application default DataSource.
*/
NONE
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
/**
* Annotation that can be applied to a test class to enable and configure
* auto-configuration of a {@link TestEntityManager}.
*
* @author Phillip Webb
* @see TestEntityManagerAutoConfiguration
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@ImportAutoConfiguration(TestEntityManagerAutoConfiguration.class)
public @interface AutoConfigureTestEntityManager {
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters;
import org.springframework.boot.test.autoconfigure.properties.PropertyMapping;
import org.springframework.boot.test.context.SpringApplicationTest;
import org.springframework.boot.test.context.SpringBootTestContextBootstrapper;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.test.context.BootstrapWith;
import org.springframework.transaction.annotation.Transactional;
/**
* Annotation that can be used in combination with {@code @RunWith(SpringRunner.class)}
* for a typical JPA test. Can be used when a test focuses <strong>only</strong> on JPA
* components.
* <p>
* Using this annotation will disable full auto-configuration and instead apply only
* configuration relevant to JPA tests.
* <p>
* By default, tests annotated with {@code @DataJpaTest} will use an embedded in-memory
* database (replacing any explicit or usually auto-configured DataSource). The
* {@link AutoConfigureTestDatabase @AutoConfigureTestDatabase} annotation can be used to
* override these settings.
* <p>
* If you are looking to load your full application configuration, but use an embedded
* database, you should consider {@link SpringApplicationTest @SpringApplicationTest}
* combined with {@link AutoConfigureTestDatabase @AutoConfigureTestDatabase} rather than
* this annotation.
*
* @author Phillip Webb
* @see AutoConfigureTestDatabase
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@ImportDataJpaAutoConfiguration
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
public @interface DataJpaTest {
/**
* If SQL output should be logged.
*/
@PropertyMapping("spring.jpa.show-sql")
boolean showSql() default true;
/**
* Determines if default filtering should be used with
* {@link SpringBootApplication @SpringBootApplication}. By default no beans are
* included.
* @see #includeFilters()
* @see #excludeFilters()
*/
boolean useDefaultFilters() default true;
/**
* A set of include filters which can be used to add otherwise filtered beans to the
* application context.
*/
Filter[] includeFilters() default {};
/**
* A set of exclude filters which can be used to filter beans that would otherwise be
* added to the application context.
*/
Filter[] excludeFilters() default {};
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.boot.test.autoconfigure.filter.AnnotationCustomizableTypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
/**
* {@link TypeExcludeFilter} for {@link DataJpaTest @DataJpaTest}.
*
* @author Phillip Webb
*/
class DataJpaTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter {
private final DataJpaTest annotation;
DataJpaTypeExcludeFilter(Class<?> testClass) {
this.annotation = AnnotatedElementUtils.getMergedAnnotation(testClass,
DataJpaTest.class);
}
@Override
protected boolean hasAnnotation() {
return this.annotation != null;
}
@Override
protected Filter[] getFilters(FilterType type) {
switch (type) {
case INCLUDE:
return this.annotation.includeFilters();
case EXCLUDE:
return this.annotation.excludeFilters();
}
throw new IllegalStateException("Unsupported type " + type);
}
@Override
protected boolean isUseDefaultFilters() {
return this.annotation.useDefaultFilters();
}
@Override
protected boolean defaultInclude(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
return false;
}
@Override
protected Set<Class<?>> getDefaultIncudes() {
return Collections.emptySet();
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
/**
* {@link ImportAutoConfiguration Auto-configuration imports} for typical Data JPA tests.
* Most tests should consider using {@link DataJpaTest @DataJpaTest} rather than using
* this annotation directly.
*
* @author Phillip Webb
* @since 1.4.0
* @see DataJpaTest
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ImportAutoConfiguration({ HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class, TransactionAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
DataSourceAutoConfiguration.class })
public @interface ImportDataJpaAutoConfiguration {
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Auto-configuration for a test database.
*
* @author Phillip Webb
* @see AutoConfigureTestDatabase
*/
@Configuration
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
class TestDatabaseAutoConfiguration {
private final Environment environment;
TestDatabaseAutoConfiguration(Environment environment) {
this.environment = environment;
}
@Bean
@ConditionalOnProperty(prefix = "spring.test.database", name = "replace", havingValue = "AUTO_CONFIGURED")
@ConditionalOnMissingBean
public DataSource dataSource() {
return new EmbeddedDataSourceFactory(this.environment).getEmbeddedDatabase();
}
@Bean
@ConditionalOnProperty(prefix = "spring.test.database", name = "replace", havingValue = "ANY", matchIfMissing = true)
public static EmbeddedDataSourceBeanFactoryPostProcessor embeddedDataSourceBeanFactoryPostProcessor() {
return new EmbeddedDataSourceBeanFactoryPostProcessor();
}
@Order(Ordered.LOWEST_PRECEDENCE)
private static class EmbeddedDataSourceBeanFactoryPostProcessor
implements BeanDefinitionRegistryPostProcessor {
private static final Log logger = LogFactory
.getLog(EmbeddedDataSourceBeanFactoryPostProcessor.class);
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, registry,
"Test Database Auto-configuration can only be "
+ "used with a ConfigurableListableBeanFactory");
process(registry, (ConfigurableListableBeanFactory) registry);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
}
private void process(BeanDefinitionRegistry registry,
ConfigurableListableBeanFactory beanFactory) {
BeanDefinitionHolder holder = getDataSourceBeanDefinition(beanFactory);
logger.info("Replacing '" + holder.getBeanName()
+ "' DataSource bean with embedded version");
registry.registerBeanDefinition(holder.getBeanName(),
createEmbeddedBeanDefinition());
}
private BeanDefinition createEmbeddedBeanDefinition() {
return new RootBeanDefinition(EmbeddedDataSourceFactoryBean.class);
}
private BeanDefinitionHolder getDataSourceBeanDefinition(
ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanNamesForType(DataSource.class);
if (!ObjectUtils.isEmpty(beanNames)) {
if (beanNames.length == 1) {
String beanName = beanNames[0];
BeanDefinition beanDefinition = beanFactory
.getBeanDefinition(beanName);
return new BeanDefinitionHolder(beanDefinition, beanName);
}
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory
.getBeanDefinition(beanName);
if (beanDefinition.isPrimary()) {
return new BeanDefinitionHolder(beanDefinition, beanName);
}
logger.warn("No primary DataSource found, "
+ "embedded version will not be used");
}
}
return null;
}
}
private static class EmbeddedDataSourceFactoryBean
implements FactoryBean<DataSource>, EnvironmentAware, InitializingBean {
private EmbeddedDataSourceFactory factory;
private EmbeddedDatabase embeddedDatabase;
@Override
public void setEnvironment(Environment environment) {
this.factory = new EmbeddedDataSourceFactory(environment);
}
@Override
public void afterPropertiesSet() throws Exception {
this.embeddedDatabase = this.factory.getEmbeddedDatabase();
}
@Override
public DataSource getObject() throws Exception {
return this.embeddedDatabase;
}
@Override
public Class<?> getObjectType() {
return EmbeddedDatabase.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
private static class EmbeddedDataSourceFactory {
private final Environment environment;
EmbeddedDataSourceFactory(Environment environment) {
this.environment = environment;
}
public EmbeddedDatabase getEmbeddedDatabase() {
EmbeddedDatabaseConnection connection = this.environment.getProperty(
"spring.test.database.connection", EmbeddedDatabaseConnection.class,
EmbeddedDatabaseConnection.NONE);
if (EmbeddedDatabaseConnection.NONE.equals(connection)) {
connection = EmbeddedDatabaseConnection.get(getClass().getClassLoader());
}
return new EmbeddedDatabaseBuilder().setType(connection.getType()).build();
}
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnitUtil;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.util.Assert;
/**
* Alternative to {@link EntityManager} for use in JPA tests. Provides a subset of
* {@link EntityManager} methods that are useful for tests as well as helper methods for
* common testing tasks such as {@link #persistFlushFind(Object) persist/flush/find}.
*
* @author Phillip Webb
* @since 1.4.0
*/
public class TestEntityManager {
private final EntityManagerFactory entityManagerFactory;
/**
* Create a new {@link TestEntityManager} instance for the given
* {@link EntityManagerFactory}.
* @param entityManagerFactory the source entity manager factory
*/
public TestEntityManager(EntityManagerFactory entityManagerFactory) {
Assert.notNull(entityManagerFactory, "EntityManagerFactory must not be null");
this.entityManagerFactory = entityManagerFactory;
}
/**
* Make an instance managed and persistent then return it's ID. Delegates to
* {@link EntityManager#persist(Object)} then {@link #getId(Object)}.
* <p>
* Helpful when setting up test data in a test: <pre class="code">
* Object entityId = this.testEntityManager.persist(new MyEntity("Spring"));
* </pre>
* @param entity the source entity
* @return the ID of the newly persisted entity
*/
public Object persistAndGetId(Object entity) {
persist(entity);
return getId(entity);
}
/**
* Make an instance managed and persistent then return it's ID. Delegates to
* {@link EntityManager#persist(Object)} then {@link #getId(Object, Class)}.
* <p>
* Helpful when setting up test data in a test: <pre class="code">
* Long entityId = this.testEntityManager.persist(new MyEntity("Spring"), Long.class);
* </pre>
* @param <T> the ID type
* @param entity the source entity
* @param idType the ID type
* @return the ID of the newly persisted entity
*/
public <T> T persistAndGetId(Object entity, Class<T> idType) {
persist(entity);
return getId(entity, idType);
}
/**
* Make an instance managed and persistent. Delegates to
* {@link EntityManager#persist(Object)} then returns the original source entity.
* <p>
* Helpful when setting up test data in a test: <pre class="code">
* MyEntity entity = this.testEntityManager.persist(new MyEntity("Spring"));
* </pre>
* @param <E> the entity type
* @param entity the entity to persist
* @return the persisted entity
*/
public <E> E persist(E entity) {
Assert.state(getId(entity) == null,
"Entity " + entity.getClass().getName() + " already has an ID");
getEntityManager().persist(entity);
return entity;
}
/**
* Make an instance managed and persistent, synchronize the persistence context to the
* underlying database and finally find the persisted entity by its ID. Delegates to
* {@link #persistAndFlush(Object)} then {@link #find(Class, Object)} with the
* {@link #getId(Object) entity ID}.
* <p>
* Helpful when ensuring that entity data is actually written and read from the
* underling database correctly.
* @param <E> the entity type
* @param entity the entity to persist
* @return the entity found using the ID of the persisted entity
*/
@SuppressWarnings("unchecked")
public <E> E persistFlushFind(E entity) {
EntityManager entityManager = getEntityManager();
persistAndFlush(entity);
Object id = getId(entity);
entityManager.detach(entity);
return (E) entityManager.find(entity.getClass(), id);
}
/**
* Make an instance managed and persistent then synchronize the persistence context to
* the underlying database. Delegates to {@link EntityManager#persist(Object)} then
* {@link #flush()} and finally returns the original source entity.
* <p>
* Helpful when setting up test data in a test: <pre class="code">
* MyEntity entity = this.testEntityManager.persistAndFlush(new MyEntity("Spring"));
* </pre>
* @param <E> the entity type
* @param entity the entity to persist
* @return the persisted entity
*/
public <E> E persistAndFlush(E entity) {
persist(entity);
flush();
return entity;
}
/**
* Merge the state of the given entity into the current persistence context. Delegates
* to {@link EntityManager#merge(Object)}
* @param <E> the entity type
* @param entity the entity to merge
* @return the merged entity
*/
public <E> E merge(E entity) {
return getEntityManager().merge(entity);
}
/**
* Remove the entity instance. Delegates to {@link EntityManager#remove(Object)}
* @param entity the entity to remove
*/
public void remove(Object entity) {
getEntityManager().remove(entity);
}
/**
* Find by primary key. Delegates to {@link EntityManager#find(Class, Object)}.
* @param <E> the entity type
* @param entityClass the entity class
* @param primaryKey the entity primary key
* @return the found entity or {@code null} if the entity does not exist
* @see #getId(Object)
*/
public <E> E find(Class<E> entityClass, Object primaryKey) {
return getEntityManager().find(entityClass, primaryKey);
}
/**
* Synchronize the persistence context to the underlying database. Delegates to
* {@link EntityManager#flush()}.
*/
public void flush() {
getEntityManager().flush();
}
/**
* Refresh the state of the instance from the database, overwriting changes made to
* the entity, if any. Delegates to {@link EntityManager#refresh(Object)}.
* @param <E> the entity type
* @param entity the entity to refresh
* @return the refreshed entity
*/
public <E> E refresh(E entity) {
getEntityManager().refresh(entity);
return entity;
}
/**
* Clear the persistence context, causing all managed entities to become detached.
* Delegates to {@link EntityManager#clear()}
*/
public void clear() {
getEntityManager().clear();
}
/**
* Remove the given entity from the persistence context, causing a managed entity to
* become detached. Delegates to {@link EntityManager#detach(Object)}.
* @param entity the entity to detach.
*/
public void detach(Object entity) {
getEntityManager().detach(entity);
}
/**
* Return the ID of the given entity. Delegates to
* {@link PersistenceUnitUtil#getIdentifier(Object)}.
* @param entity the source entity
* @return the ID of the entity or {@code null}
* @see #getId(Object, Class)
*/
public Object getId(Object entity) {
return this.entityManagerFactory.getPersistenceUnitUtil().getIdentifier(entity);
}
/**
* Return the ID of the given entity cast to a specific type. Delegates to
* {@link PersistenceUnitUtil#getIdentifier(Object)}.
* @param <T> the ID type
* @param entity the source entity
* @param idType the expected ID type
* @return the ID of the entity or {@code null}
* @see #getId(Object)
*/
@SuppressWarnings("unchecked")
public <T> T getId(Object entity, Class<T> idType) {
Object id = getId(entity);
Assert.isInstanceOf(idType, id, "ID missmatch");
return (T) id;
}
/**
* Return the underlying {@link EntityManager} that's actually used to perform all
* operations.
* @return the entity manager
*/
public final EntityManager getEntityManager() {
EntityManager manager = EntityManagerFactoryUtils
.getTransactionalEntityManager(this.entityManagerFactory);
Assert.state(manager != null, "No transactional EnitiyManager found");
return manager;
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.persistence.EntityManagerFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Auto-configuration for {@link TestEntityManager}.
*
* @author Phillip Webb
* @see AutoConfigureTestEntityManager
*/
@Configuration
@ConditionalOnClass({ EntityManagerFactory.class })
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
class TestEntityManagerAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TestEntityManager testEntityManager(
EntityManagerFactory entityManagerFactory) {
return new TestEntityManager(entityManagerFactory);
}
}
/*
* Copyright 2012-2016 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.
*/
/**
* Auto-configuration for Data JPA tests.
*/
package org.springframework.boot.test.autoconfigure.orm.jpa;
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link DataJpaTest}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@DataJpaTest
public class DataJpaTestIntegrationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Autowired
private ApplicationContext applicationContext;
@Test
public void testEntityManager() throws Exception {
ExampleEntity entity = this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.flush();
Object id = this.entities.getId(entity);
ExampleEntity found = this.entities.find(ExampleEntity.class, id);
assertThat(found.getName()).isEqualTo("spring");
}
@Test
public void testEntityManagerPersistAndGetId() throws Exception {
Long id = this.entities.persistAndGetId(new ExampleEntity("spring", "123"),
Long.class);
assertThat(id).isNotNull();
}
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void replacesDefinedDatasourceWithEmbeddedDefault() throws Exception {
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
assertThat(product).isEqualTo("H2");
}
@Test
public void didNotInjectExampleComponent() throws Exception {
this.thrown.expect(NoSuchBeanDefinitionException.class);
this.applicationContext.getBean(ExampleComponent.class);
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestDatabase.Replace;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link DataJpaTest}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.AUTO_CONFIGURED, connection = EmbeddedDatabaseConnection.HSQL)
public class DataJpaTestWithAutoConfigureTestDatabaseReplaceAutoConfiguredIntegrationTests {
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void replacesAutoConfiguredDataSource() throws Exception {
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
assertThat(product).startsWith("HSQL");
}
@Configuration
@EnableAutoConfiguration // Will auto-configure H2
static class Config {
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestDatabase.Replace;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link DataJpaTest}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.AUTO_CONFIGURED)
public class DataJpaTestWithAutoConfigureTestDatabaseReplaceAutoConfiguredWithoutOverrideIntegrationTests {
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void usesDefaultEmbeddedDatabase() throws Exception {
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
// @AutoConfigureTestDatabase would use H2 but HSQL is manually defined
assertThat(product).startsWith("HSQL");
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link DataJpaTest}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.HSQL)
public class DataJpaTestWithAutoConfigureTestDatabaseReplaceExplicitIntegrationTests {
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void replacesDefinedDatasourceWithExplicit() throws Exception {
// H2 is explicitly defined by HSQL is the override
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
assertThat(product).startsWith("HSQL");
}
@Configuration
@EnableAutoConfiguration
static class Config {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2);
return builder.build();
}
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureTestDatabase.Replace;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link DataJpaTest}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class DataJpaTestWithAutoConfigureTestDatabaseReplaceNoneIntegrationTests {
@Autowired
private TestEntityManager entities;
@Autowired
private ExampleRepository repository;
@Autowired
private DataSource dataSource;
@Test
public void testRepository() throws Exception {
this.entities.persist(new ExampleEntity("spring", "123"));
this.entities.persist(new ExampleEntity("boot", "124"));
this.entities.flush();
ExampleEntity found = this.repository.findByReference("124");
assertThat(found.getName()).isEqualTo("boot");
}
@Test
public void usesDefaultEmbeddedDatabase() throws Exception {
// HSQL is explicitly defined and should not be replaced
String product = this.dataSource.getConnection().getMetaData()
.getDatabaseProductName();
assertThat(product).startsWith("HSQL");
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import org.springframework.stereotype.Component;
/**
* Example component used with {@link DataJpaTest} tests.
*
* @author Phillip Webb
*/
@Component
public class ExampleComponent {
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
/**
* Example {@link SpringBootApplication} used with {@link DataJpaTest} tests.
*
* @author Phillip Webb
*/
@SpringBootApplication
public class ExampleDataJpaApplication {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL);
return builder.build();
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* Example entity used with {@link DataJpaTest} tests.
*
* @author Phillip Webb
*/
@Entity
public class ExampleEntity {
@Id
@GeneratedValue
private Long id;
private String name;
private String reference;
protected ExampleEntity() {
}
public ExampleEntity(String name, String reference) {
super();
this.name = name;
this.reference = reference;
}
public String getName() {
return this.name;
}
public String getReference() {
return this.reference;
}
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import org.springframework.data.repository.Repository;
/**
* Example repository used with {@link DataJpaTest} tests.
*
* @author Phillip Webb
*/
public interface ExampleRepository extends Repository<ExampleEntity, Long> {
ExampleEntity findByReference(String reference);
}
/*
* Copyright 2012-2016 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.test.autoconfigure.orm.jpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnitUtil;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.orm.jpa.EntityManagerHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link TestEntityManager}.
*
* @author Phillip Webb
*/
public class TestEntityManagerTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Mock
private EntityManagerFactory entityManagerFactory;
@Mock
private EntityManager entityManager;
@Mock
private PersistenceUnitUtil persistenceUnitUtil;
private TestEntityManager testEntityManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.testEntityManager = new TestEntityManager(this.entityManagerFactory);
given(this.entityManagerFactory.getPersistenceUnitUtil())
.willReturn(this.persistenceUnitUtil);
}
@Test
public void createWhenEntityManagerIsNullShouldThrowException() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("EntityManagerFactory must not be null");
new TestEntityManager(null);
}
@Test
public void persistAndGetIdShouldPersistAndGetId() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(null, 123);
Object result = this.testEntityManager.persistAndGetId(entity);
verify(this.entityManager).persist(entity);
assertThat(result).isEqualTo(123);
}
@Test
public void persistAndGetIdForTypeShouldPersistAndGetId() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(null, 123);
Integer result = this.testEntityManager.persistAndGetId(entity, Integer.class);
verify(this.entityManager).persist(entity);
assertThat(result).isEqualTo(123);
}
@Test
public void persistShouldPersist() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
TestEntity result = this.testEntityManager.persist(entity);
verify(this.entityManager).persist(entity);
assertThat(result).isSameAs(entity);
}
@Test
public void persistWhenAlreadyHasIdShouldThrowException() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(123);
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(
"Entity " + TestEntity.class.getName() + " already has an ID");
this.testEntityManager.persistAndGetId(entity, Integer.class);
}
@Test
public void persistAndFlushShouldPersistAndFlush() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
TestEntity result = this.testEntityManager.persistAndFlush(entity);
verify(this.entityManager).persist(entity);
verify(this.entityManager).flush();
assertThat(result).isSameAs(entity);
}
@Test
public void persistFlushFindShouldPersistAndFlushAndFind() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
TestEntity found = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(null, 123);
given(this.entityManager.find(TestEntity.class, 123)).willReturn(found);
TestEntity result = this.testEntityManager.persistFlushFind(entity);
verify(this.entityManager).persist(entity);
verify(this.entityManager).flush();
assertThat(result).isSameAs(found);
}
@Test
public void mergeShouldMerge() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
given(this.entityManager.merge(entity)).willReturn(entity);
TestEntity result = this.testEntityManager.merge(entity);
verify(this.entityManager).merge(entity);
assertThat(result).isSameAs(entity);
}
@Test
public void removeShouldRemove() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
this.testEntityManager.remove(entity);
verify(this.entityManager).remove(entity);
}
@Test
public void findShouldFind() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
given(this.entityManager.find(TestEntity.class, 123)).willReturn(entity);
TestEntity result = this.testEntityManager.find(TestEntity.class, 123);
assertThat(result).isSameAs(entity);
}
@Test
public void flushShouldFlush() throws Exception {
bindEntityManager();
this.testEntityManager.flush();
verify(this.entityManager).flush();
}
@Test
public void refreshShouldRefresh() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
this.testEntityManager.refresh(entity);
verify(this.entityManager).refresh(entity);
}
@Test
public void clearShouldClear() throws Exception {
bindEntityManager();
this.testEntityManager.clear();
verify(this.entityManager).clear();
}
@Test
public void detachShouldDetach() throws Exception {
bindEntityManager();
TestEntity entity = new TestEntity();
this.testEntityManager.detach(entity);
verify(this.entityManager).detach(entity);
}
@Test
public void getIdForTypeShouldGetId() throws Exception {
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(123);
Integer result = this.testEntityManager.getId(entity, Integer.class);
assertThat(result).isEqualTo(123);
}
@Test
public void getIdForTypeWhenTypeIsWrongShouldThrowException() throws Exception {
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(123);
this.thrown.expectMessage("ID missmatch Object of class [java.lang.Integer] "
+ "must be an instance of class java.lang.Long");
this.testEntityManager.getId(entity, Long.class);
}
@Test
public void getIdShouldGetId() throws Exception {
TestEntity entity = new TestEntity();
given(this.persistenceUnitUtil.getIdentifier(entity)).willReturn(123);
Object result = this.testEntityManager.getId(entity);
assertThat(result).isEqualTo(123);
}
@Test
public void getEntityManagerShouldGetEntityManager() throws Exception {
bindEntityManager();
assertThat(this.testEntityManager.getEntityManager())
.isEqualTo(this.entityManager);
}
@Test
public void getEntityManagerWhenNotSetShouldThrowException() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("No transactional EnitiyManager found");
this.testEntityManager.getEntityManager();
}
private void bindEntityManager() {
EntityManagerHolder holder = new EntityManagerHolder(this.entityManager);
TransactionSynchronizationManager.bindResource(this.entityManagerFactory, holder);
}
static class TestEntity {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment