HHH-15344 - Ability to apply testing annotations at method-level
- `@SessionFactory`
This commit is contained in:
parent
edc95df72a
commit
ff2cd561f5
|
@ -1,4 +1,7 @@
|
||||||
The `hibernate-testing` module of Hibernate ORM defines utilities for writing
|
The `hibernate-testing` module of Hibernate ORM defines utilities for writing
|
||||||
tests easier....
|
tests easier.
|
||||||
|
|
||||||
// todo : write more (duh)
|
This documentation focuses on the JUnit 5 & annotation based testing support...
|
||||||
|
|
||||||
|
|
||||||
|
// todo (6.1) : write more (duh)
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.orm.junit;
|
package org.hibernate.testing.orm.junit;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -48,12 +49,62 @@ public class DomainModelExtension
|
||||||
|
|
||||||
private static final String MODEL_KEY = MetadataImplementor.class.getName();
|
private static final String MODEL_KEY = MetadataImplementor.class.getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended for use from external consumers. Will never create a scope, just
|
||||||
|
* attempt to consume an already created and stored one
|
||||||
|
*/
|
||||||
|
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
|
||||||
|
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
|
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
||||||
|
if ( existing != null ) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException( "Could not locate DomainModelScope : " + context.getDisplayName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DomainModelScope resolveForMethodLevelSessionFactoryScope(ExtensionContext context) {
|
||||||
|
assert context.getTestMethod().isPresent();
|
||||||
|
|
||||||
|
// if the test defines `@DomainModel` at the class-level but not at the method-level,
|
||||||
|
// we will run into problems with a shared `TypeConfiguration`. In this case, we need
|
||||||
|
// to create a new DomainModelScope (well ask the DomainModelExtension to create it)
|
||||||
|
// and store it relative to the method-context
|
||||||
|
//
|
||||||
|
// first, look for `@DomainModel` at the method-level. if it is there, no problem.
|
||||||
|
// otherwise we need to "act like it is" and create a method-level DomainModelScope
|
||||||
|
|
||||||
|
final Object testInstance = context.getRequiredTestInstance();
|
||||||
|
final Method testMethod = context.getRequiredTestMethod();
|
||||||
|
|
||||||
|
final Optional<DomainModel> methodLevelAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
testMethod,
|
||||||
|
DomainModel.class
|
||||||
|
);
|
||||||
|
if ( methodLevelAnnRef.isPresent() ) {
|
||||||
|
// just return the existing one
|
||||||
|
return findDomainModelScope( testInstance, context );
|
||||||
|
}
|
||||||
|
|
||||||
|
final Optional<DomainModel> classLevelAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getRequiredTestClass(),
|
||||||
|
DomainModel.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( classLevelAnnRef.isPresent()
|
||||||
|
|| testInstance instanceof DomainModelProducer ) {
|
||||||
|
final DomainModelScope created = createDomainModelScope( testInstance, classLevelAnnRef, context );
|
||||||
|
locateExtensionStore( testInstance, context ).put( MODEL_KEY, created );
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException( "Could not locate @DomainModel to use with method-level @SessionFactory: " + context.getDisplayName() );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||||
assert context.getTestClass().isPresent();
|
|
||||||
|
|
||||||
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
|
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
|
||||||
context.getElement().get(),
|
context.getRequiredTestClass(),
|
||||||
DomainModel.class
|
DomainModel.class
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -66,10 +117,6 @@ public class DomainModelExtension
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeEach(ExtensionContext context) {
|
public void beforeEach(ExtensionContext context) {
|
||||||
assert context.getTestMethod().isPresent();
|
|
||||||
assert context.getRequiredTestMethod() == context.getElement().get();
|
|
||||||
assert context.getTestInstance().isPresent();
|
|
||||||
|
|
||||||
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
|
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
|
||||||
context.getElement().get(),
|
context.getElement().get(),
|
||||||
DomainModel.class
|
DomainModel.class
|
||||||
|
@ -198,16 +245,6 @@ public class DomainModelExtension
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
|
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
|
||||||
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
|
||||||
if ( existing != null ) {
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RuntimeException( "Could not locate @DomainModel annotation : " + context.getDisplayName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void applyCacheSettings(Metadata metadata, boolean overrideCacheStrategy, String cacheConcurrencyStrategy) {
|
protected static void applyCacheSettings(Metadata metadata, boolean overrideCacheStrategy, String cacheConcurrencyStrategy) {
|
||||||
if ( !overrideCacheStrategy ) {
|
if ( !overrideCacheStrategy ) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -61,10 +61,7 @@ public class ServiceRegistryExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeEach(ExtensionContext context) throws Exception {
|
public void beforeEach(ExtensionContext context) {
|
||||||
assert context.getTestMethod().isPresent();
|
|
||||||
assert context.getRequiredTestMethod() == context.getElement().get();
|
|
||||||
|
|
||||||
Optional<BootstrapServiceRegistry> bsrAnnRef = AnnotationSupport.findAnnotation(
|
Optional<BootstrapServiceRegistry> bsrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
context.getElement().get(),
|
context.getElement().get(),
|
||||||
BootstrapServiceRegistry.class
|
BootstrapServiceRegistry.class
|
||||||
|
|
|
@ -30,7 +30,7 @@ import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.ActionGroup
|
||||||
|
|
||||||
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
import org.hibernate.testing.jdbc.SQLStatementInspector;
|
||||||
import org.hibernate.testing.orm.transaction.TransactionUtil;
|
import org.hibernate.testing.orm.transaction.TransactionUtil;
|
||||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
|
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
|
||||||
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
|
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
|
||||||
|
@ -48,15 +48,15 @@ import org.jboss.logging.Logger;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class SessionFactoryExtension
|
public class SessionFactoryExtension
|
||||||
implements TestInstancePostProcessor, AfterAllCallback, TestExecutionExceptionHandler {
|
implements TestInstancePostProcessor, BeforeEachCallback, TestExecutionExceptionHandler {
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger( SessionFactoryExtension.class );
|
private static final Logger log = Logger.getLogger( SessionFactoryExtension.class );
|
||||||
private static final String SESSION_FACTORY_KEY = SessionFactoryScope.class.getName();
|
private static final String SESSION_FACTORY_KEY = SessionFactoryScope.class.getName();
|
||||||
|
|
||||||
private static ExtensionContext.Store locateExtensionStore(Object testInstance, ExtensionContext context) {
|
/**
|
||||||
return JUnitHelper.locateExtensionStore( SessionFactoryExtension.class, context, testInstance );
|
* Intended for use from external consumers. Will never create a scope, just
|
||||||
}
|
* attempt to consume an already created and stored one
|
||||||
|
*/
|
||||||
public static SessionFactoryScope findSessionFactoryScope(Object testInstance, ExtensionContext context) {
|
public static SessionFactoryScope findSessionFactoryScope(Object testInstance, ExtensionContext context) {
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
final SessionFactoryScope existing = (SessionFactoryScope) store.get( SESSION_FACTORY_KEY );
|
final SessionFactoryScope existing = (SessionFactoryScope) store.get( SESSION_FACTORY_KEY );
|
||||||
|
@ -64,9 +64,55 @@ public class SessionFactoryExtension
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionFactoryProducer producer = null;
|
throw new RuntimeException( "Could not locate SessionFactoryScope : " + context.getDisplayName() );
|
||||||
|
}
|
||||||
|
|
||||||
final DomainModelScope domainModelScope = DomainModelExtension.findDomainModelScope( testInstance, context );
|
@Override
|
||||||
|
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||||
|
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
||||||
|
|
||||||
|
final Optional<SessionFactory> sfAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getRequiredTestClass(),
|
||||||
|
SessionFactory.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( sfAnnRef.isPresent()
|
||||||
|
|| SessionFactoryProducer.class.isAssignableFrom( context.getRequiredTestClass() ) ) {
|
||||||
|
final DomainModelScope domainModelScope = DomainModelExtension.findDomainModelScope( testInstance, context );
|
||||||
|
final SessionFactoryScope created = createSessionFactoryScope( testInstance, sfAnnRef, domainModelScope, context );
|
||||||
|
locateExtensionStore( testInstance, context ).put( SESSION_FACTORY_KEY, created );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEach(ExtensionContext context) {
|
||||||
|
final Optional<SessionFactory> sfAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getRequiredTestMethod(),
|
||||||
|
SessionFactory.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( sfAnnRef.isEmpty() ) {
|
||||||
|
// assume the annotations are defined on the class-level...
|
||||||
|
// will be validated by the parameter-resolver or SFS-extension
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final DomainModelScope domainModelScope = DomainModelExtension.resolveForMethodLevelSessionFactoryScope( context );
|
||||||
|
final SessionFactoryScope created = createSessionFactoryScope( context.getRequiredTestInstance(), sfAnnRef, domainModelScope, context );
|
||||||
|
final ExtensionContext.Store extensionStore = locateExtensionStore( context.getRequiredTestInstance(), context );
|
||||||
|
extensionStore.put( SESSION_FACTORY_KEY, created );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExtensionContext.Store locateExtensionStore(Object testInstance, ExtensionContext context) {
|
||||||
|
return JUnitHelper.locateExtensionStore( SessionFactoryExtension.class, context, testInstance );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SessionFactoryScopeImpl createSessionFactoryScope(
|
||||||
|
Object testInstance,
|
||||||
|
Optional<SessionFactory> sfAnnRef,
|
||||||
|
DomainModelScope domainModelScope,
|
||||||
|
ExtensionContext context) {
|
||||||
|
SessionFactoryProducer producer = null;
|
||||||
|
|
||||||
if ( testInstance instanceof SessionFactoryProducer ) {
|
if ( testInstance instanceof SessionFactoryProducer ) {
|
||||||
producer = (SessionFactoryProducer) testInstance;
|
producer = (SessionFactoryProducer) testInstance;
|
||||||
|
@ -76,13 +122,8 @@ public class SessionFactoryExtension
|
||||||
throw new RuntimeException( "Unable to determine how to handle given ExtensionContext : " + context.getDisplayName() );
|
throw new RuntimeException( "Unable to determine how to handle given ExtensionContext : " + context.getDisplayName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
final Optional<SessionFactory> sfAnnWrappper = AnnotationSupport.findAnnotation(
|
if ( sfAnnRef.isPresent() ) {
|
||||||
context.getElement().get(),
|
final SessionFactory sessionFactoryConfig = sfAnnRef.get();
|
||||||
SessionFactory.class
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( sfAnnWrappper.isPresent() ) {
|
|
||||||
final SessionFactory sessionFactoryConfig = sfAnnWrappper.get();
|
|
||||||
|
|
||||||
producer = model -> {
|
producer = model -> {
|
||||||
try {
|
try {
|
||||||
|
@ -131,8 +172,6 @@ public class SessionFactoryExtension
|
||||||
producer
|
producer
|
||||||
);
|
);
|
||||||
|
|
||||||
locateExtensionStore( testInstance, context ).put( SESSION_FACTORY_KEY, sfScope );
|
|
||||||
|
|
||||||
if ( testInstance instanceof SessionFactoryScopeAware ) {
|
if ( testInstance instanceof SessionFactoryScopeAware ) {
|
||||||
( (SessionFactoryScopeAware) testInstance ).injectSessionFactoryScope( sfScope );
|
( (SessionFactoryScopeAware) testInstance ).injectSessionFactoryScope( sfScope );
|
||||||
}
|
}
|
||||||
|
@ -180,32 +219,6 @@ public class SessionFactoryExtension
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
|
||||||
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
|
||||||
|
|
||||||
findSessionFactoryScope( testInstance, context );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterAll(ExtensionContext context) {
|
|
||||||
log.tracef( "#afterAll(%s)", context.getDisplayName() );
|
|
||||||
|
|
||||||
final Object testInstance = context.getRequiredTestInstance();
|
|
||||||
|
|
||||||
if ( testInstance instanceof SessionFactoryScopeAware ) {
|
|
||||||
( (SessionFactoryScopeAware) testInstance ).injectSessionFactoryScope( null );
|
|
||||||
}
|
|
||||||
|
|
||||||
final SessionFactoryScopeImpl removed = (SessionFactoryScopeImpl) locateExtensionStore( testInstance, context ).remove( SESSION_FACTORY_KEY );
|
|
||||||
if ( removed != null ) {
|
|
||||||
removed.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( testInstance instanceof SessionFactoryScopeAware ) {
|
|
||||||
( (SessionFactoryScopeAware) testInstance ).injectSessionFactoryScope( null );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
|
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
package org.hibernate.testing.annotations.methods;
|
||||||
|
|
||||||
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.annotations.AnEntity;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel( annotatedClasses = AnEntity.class )
|
||||||
|
@SessionFactory( generateStatistics = true )
|
||||||
|
public class SessionFactoryTesting {
|
||||||
|
@Test
|
||||||
|
public void testClassLevelAnnotations(SessionFactoryScope scope) {
|
||||||
|
final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
assertThat( statistics.isStatisticsEnabled() ).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SessionFactory()
|
||||||
|
public void testMethodLevelAnnotations(SessionFactoryScope scope) {
|
||||||
|
final StatisticsImplementor statistics = scope.getSessionFactory().getStatistics();
|
||||||
|
assertThat( statistics.isStatisticsEnabled() ).isFalse();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue