HHH-15344 - Ability to apply testing annotations at method-level
- `@ServiceRegistry` - `@BootstrapServiceRegistry`
This commit is contained in:
parent
763d1764cd
commit
edc95df72a
|
@ -45,8 +45,6 @@ public interface Integrator {
|
||||||
* @param metadata The fully initialized boot-time mapping model
|
* @param metadata The fully initialized boot-time mapping model
|
||||||
* @param bootstrapContext The context for bootstrapping of the SessionFactory
|
* @param bootstrapContext The context for bootstrapping of the SessionFactory
|
||||||
* @param sessionFactory The SessionFactory being created
|
* @param sessionFactory The SessionFactory being created
|
||||||
*
|
|
||||||
* todo (6.0) : why pass the `serviceRegistry`? Why not just grab it from the SessionFactory?
|
|
||||||
*/
|
*/
|
||||||
@Incubating
|
@Incubating
|
||||||
default void integrate(
|
default void integrate(
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
The `hibernate-testing` module of Hibernate ORM defines utilities for writing
|
||||||
|
tests easier....
|
||||||
|
|
||||||
|
// todo : write more (duh)
|
|
@ -99,7 +99,7 @@ public class DomainModelExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExtensionContext.Store locateExtensionStore(Object testInstance, ExtensionContext context) {
|
private static ExtensionContext.Store locateExtensionStore(Object testInstance, ExtensionContext context) {
|
||||||
return JUnitHelper.locateExtensionStore( ServiceRegistryExtension.class, context, testInstance );
|
return JUnitHelper.locateExtensionStore( DomainModelExtension.class, context, testInstance );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DomainModelScope createDomainModelScope(
|
private static DomainModelScope createDomainModelScope(
|
||||||
|
@ -199,29 +199,15 @@ public class DomainModelExtension
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
|
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
|
||||||
// todo : allow for method-level
|
|
||||||
|
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
|
||||||
if ( existing != null ) {
|
if ( existing != null ) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
|
|
||||||
context.getElement().get(),
|
|
||||||
DomainModel.class
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( domainModelAnnRef.isEmpty() ) {
|
|
||||||
throw new RuntimeException( "Could not locate @DomainModel annotation : " + context.getDisplayName() );
|
throw new RuntimeException( "Could not locate @DomainModel annotation : " + context.getDisplayName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
final DomainModelScope created = createDomainModelScope( testInstance, domainModelAnnRef, context );
|
|
||||||
locateExtensionStore( testInstance, context ).put( MODEL_KEY, created );
|
|
||||||
|
|
||||||
return created;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.hibernate.service.spi.ServiceContributor;
|
||||||
|
|
||||||
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService;
|
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService;
|
||||||
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService.JavaServiceDescriptor;
|
import org.hibernate.testing.boot.ExtraJavaServicesClassLoaderService.JavaServiceDescriptor;
|
||||||
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;
|
||||||
|
@ -37,14 +37,84 @@ import org.jboss.logging.Logger;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class ServiceRegistryExtension
|
public class ServiceRegistryExtension
|
||||||
implements TestInstancePostProcessor, AfterAllCallback, TestExecutionExceptionHandler {
|
implements TestInstancePostProcessor, BeforeEachCallback, TestExecutionExceptionHandler {
|
||||||
private static final Logger log = Logger.getLogger( ServiceRegistryExtension.class );
|
private static final Logger log = Logger.getLogger( ServiceRegistryExtension.class );
|
||||||
private static final String REGISTRY_KEY = ServiceRegistryScope.class.getName();
|
private static final String REGISTRY_KEY = ServiceRegistryScope.class.getName();
|
||||||
|
|
||||||
public static StandardServiceRegistry findServiceRegistry(
|
@Override
|
||||||
Object testInstance,
|
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||||
ExtensionContext context) {
|
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
||||||
return findServiceRegistryScope( testInstance, context ).getRegistry();
|
|
||||||
|
assert context.getTestClass().isPresent();
|
||||||
|
|
||||||
|
final Optional<BootstrapServiceRegistry> bsrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getElement().get(),
|
||||||
|
BootstrapServiceRegistry.class
|
||||||
|
);
|
||||||
|
final Optional<ServiceRegistry> ssrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getElement().get(),
|
||||||
|
ServiceRegistry.class
|
||||||
|
);
|
||||||
|
|
||||||
|
final ServiceRegistryScope created = createServiceRegistryScope( testInstance, bsrAnnRef, ssrAnnRef, context );
|
||||||
|
locateExtensionStore( testInstance, context ).put( REGISTRY_KEY, created );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeEach(ExtensionContext context) throws Exception {
|
||||||
|
assert context.getTestMethod().isPresent();
|
||||||
|
assert context.getRequiredTestMethod() == context.getElement().get();
|
||||||
|
|
||||||
|
Optional<BootstrapServiceRegistry> bsrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getElement().get(),
|
||||||
|
BootstrapServiceRegistry.class
|
||||||
|
);
|
||||||
|
Optional<ServiceRegistry> ssrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getElement().get(),
|
||||||
|
ServiceRegistry.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( bsrAnnRef.isEmpty() && ssrAnnRef.isEmpty() ) {
|
||||||
|
// assume the annotations are defined on the class-level...
|
||||||
|
// will be validated by the parameter-resolver or consuming extension
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ( bsrAnnRef.isPresent() && ssrAnnRef.isPresent() ) {
|
||||||
|
// the method has both - use them -> fall through
|
||||||
|
}
|
||||||
|
else if ( bsrAnnRef.isPresent() ) {
|
||||||
|
// the method has BootstrapServiceRegistry but not ServiceRegistry
|
||||||
|
//
|
||||||
|
// see if there is a ServiceRegistry at the class-level:
|
||||||
|
// yes -> use this class-level one
|
||||||
|
// no -> treat it as implicit
|
||||||
|
|
||||||
|
ssrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getRequiredTestClass(),
|
||||||
|
ServiceRegistry.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ( ssrAnnRef.isPresent() ) {
|
||||||
|
// the method has ServiceRegistry but not BootstrapServiceRegistry
|
||||||
|
//
|
||||||
|
// see if there is a BootstrapServiceRegistry at the class-level:
|
||||||
|
// yes -> use this class-level one
|
||||||
|
// no -> treat it as implicit
|
||||||
|
|
||||||
|
bsrAnnRef = AnnotationSupport.findAnnotation(
|
||||||
|
context.getRequiredTestClass(),
|
||||||
|
BootstrapServiceRegistry.class
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException( "Some clever text" );
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object testInstance = context.getRequiredTestInstance();
|
||||||
|
|
||||||
|
final ServiceRegistryScope created = createServiceRegistryScope( testInstance, bsrAnnRef, ssrAnnRef, context );
|
||||||
|
final ExtensionContext.Store extensionStore = locateExtensionStore( testInstance, context );
|
||||||
|
extensionStore.put( REGISTRY_KEY, created );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExtensionContext.Store locateExtensionStore(
|
private static ExtensionContext.Store locateExtensionStore(
|
||||||
|
@ -57,22 +127,28 @@ public class ServiceRegistryExtension
|
||||||
log.tracef( "#findServiceRegistryScope(%s, %s)", testInstance, context.getDisplayName() );
|
log.tracef( "#findServiceRegistryScope(%s, %s)", testInstance, context.getDisplayName() );
|
||||||
|
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
|
final ServiceRegistryScopeImpl existingScope = (ServiceRegistryScopeImpl) store.get( REGISTRY_KEY );
|
||||||
ServiceRegistryScopeImpl existingScope = (ServiceRegistryScopeImpl) store.get( REGISTRY_KEY );
|
|
||||||
|
|
||||||
if ( existingScope == null ) {
|
if ( existingScope == null ) {
|
||||||
|
throw new RuntimeException( "No ServiceRegistryScope known in context" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceRegistryScopeImpl createServiceRegistryScope(
|
||||||
|
Object testInstance,
|
||||||
|
Optional<BootstrapServiceRegistry> bsrAnnRef,
|
||||||
|
Optional<ServiceRegistry> ssrAnnRef,
|
||||||
|
ExtensionContext context) {
|
||||||
log.debugf( "Creating ServiceRegistryScope - %s", context.getDisplayName() );
|
log.debugf( "Creating ServiceRegistryScope - %s", context.getDisplayName() );
|
||||||
|
|
||||||
final BootstrapServiceRegistryProducer bsrProducer;
|
final BootstrapServiceRegistryProducer bsrProducer;
|
||||||
|
|
||||||
final Optional<BootstrapServiceRegistry> bsrAnnWrapper = AnnotationSupport.findAnnotation(
|
//noinspection OptionalIsPresent
|
||||||
context.getElement().get(),
|
if ( bsrAnnRef.isPresent() ) {
|
||||||
BootstrapServiceRegistry.class
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( bsrAnnWrapper.isPresent() ) {
|
|
||||||
bsrProducer = bsrBuilder -> {
|
bsrProducer = bsrBuilder -> {
|
||||||
final BootstrapServiceRegistry bsrAnn = bsrAnnWrapper.get();
|
final BootstrapServiceRegistry bsrAnn = bsrAnnRef.get();
|
||||||
configureJavaServices( bsrAnn, bsrBuilder );
|
configureJavaServices( bsrAnn, bsrBuilder );
|
||||||
configureIntegrators( bsrAnn, bsrBuilder );
|
configureIntegrators( bsrAnn, bsrBuilder );
|
||||||
|
|
||||||
|
@ -89,30 +165,24 @@ public class ServiceRegistryExtension
|
||||||
ssrProducer = (ServiceRegistryProducer) testInstance;
|
ssrProducer = (ServiceRegistryProducer) testInstance;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ssrProducer = new ServiceRegistryProducerImpl(context);
|
ssrProducer = new ServiceRegistryProducerImpl( ssrAnnRef );
|
||||||
}
|
}
|
||||||
|
|
||||||
final ServiceRegistryScopeImpl scope = new ServiceRegistryScopeImpl( bsrProducer, ssrProducer );
|
final ServiceRegistryScopeImpl scope = new ServiceRegistryScopeImpl( bsrProducer, ssrProducer );
|
||||||
scope.getRegistry();
|
scope.getRegistry();
|
||||||
|
|
||||||
locateExtensionStore( testInstance, context ).put( REGISTRY_KEY, scope );
|
|
||||||
|
|
||||||
if ( testInstance instanceof ServiceRegistryScopeAware ) {
|
if ( testInstance instanceof ServiceRegistryScopeAware ) {
|
||||||
( (ServiceRegistryScopeAware) testInstance ).injectServiceRegistryScope( scope );
|
( (ServiceRegistryScopeAware) testInstance ).injectServiceRegistryScope( scope );
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
return existingScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ServiceRegistryProducerImpl implements ServiceRegistryProducer{
|
private static class ServiceRegistryProducerImpl implements ServiceRegistryProducer{
|
||||||
private final ExtensionContext context;
|
private final Optional<ServiceRegistry> ssrAnnRef;
|
||||||
public ServiceRegistryProducerImpl(ExtensionContext context) {
|
|
||||||
this.context = context;
|
public ServiceRegistryProducerImpl(Optional<ServiceRegistry> ssrAnnRef) {
|
||||||
if ( !context.getElement().isPresent() ) {
|
this.ssrAnnRef = ssrAnnRef;
|
||||||
throw new RuntimeException( "Unable to determine how to handle given ExtensionContext : " + context.getDisplayName() );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,13 +190,8 @@ public class ServiceRegistryExtension
|
||||||
// set some baseline test settings
|
// set some baseline test settings
|
||||||
ssrb.applySetting( AvailableSettings.STATEMENT_INSPECTOR, org.hibernate.testing.jdbc.SQLStatementInspector.class );
|
ssrb.applySetting( AvailableSettings.STATEMENT_INSPECTOR, org.hibernate.testing.jdbc.SQLStatementInspector.class );
|
||||||
|
|
||||||
final Optional<ServiceRegistry> ssrAnnWrapper = AnnotationSupport.findAnnotation(
|
if ( ssrAnnRef.isPresent() ) {
|
||||||
context.getElement().get(),
|
final ServiceRegistry serviceRegistryAnn = ssrAnnRef.get();
|
||||||
ServiceRegistry.class
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( ssrAnnWrapper.isPresent() ) {
|
|
||||||
final ServiceRegistry serviceRegistryAnn = ssrAnnWrapper.get();
|
|
||||||
configureServices( serviceRegistryAnn, ssrb );
|
configureServices( serviceRegistryAnn, ssrb );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,28 +283,22 @@ public class ServiceRegistryExtension
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
// public void afterAll(ExtensionContext context) {
|
||||||
log.tracef( "#postProcessTestInstance(%s, %s)", testInstance, context.getDisplayName() );
|
// log.tracef( "#afterAll(%s)", context.getDisplayName() );
|
||||||
findServiceRegistryScope( testInstance, context );
|
//
|
||||||
}
|
// final Object testInstance = context.getRequiredTestInstance();
|
||||||
|
//
|
||||||
@Override
|
// if ( testInstance instanceof ServiceRegistryScopeAware ) {
|
||||||
public void afterAll(ExtensionContext context) {
|
// ( (ServiceRegistryScopeAware) testInstance ).injectServiceRegistryScope( null );
|
||||||
log.tracef( "#afterAll(%s)", context.getDisplayName() );
|
// }
|
||||||
|
//
|
||||||
final Object testInstance = context.getRequiredTestInstance();
|
// final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
||||||
|
// final ServiceRegistryScopeImpl scope = (ServiceRegistryScopeImpl) store.remove( REGISTRY_KEY );
|
||||||
if ( testInstance instanceof ServiceRegistryScopeAware ) {
|
// if ( scope != null ) {
|
||||||
( (ServiceRegistryScopeAware) testInstance ).injectServiceRegistryScope( null );
|
// scope.close();
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
|
|
||||||
final ServiceRegistryScopeImpl scope = (ServiceRegistryScopeImpl) store.remove( REGISTRY_KEY );
|
|
||||||
if ( scope != null ) {
|
|
||||||
scope.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
|
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||||
|
import org.hibernate.service.spi.ServiceContributor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||||
|
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Setting;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@BootstrapServiceRegistry(javaServices = @BootstrapServiceRegistry.JavaService(
|
||||||
|
role = ServiceContributor.class,
|
||||||
|
impl = ServiceRegistryTesting.ServiceContributor1.class
|
||||||
|
))
|
||||||
|
@ServiceRegistry( settings = @Setting( name = "setting", value = "class-level"))
|
||||||
|
public class ServiceRegistryTesting {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassLevel(ServiceRegistryScope scope) {
|
||||||
|
scope.withService( ConfigurationService.class, (configurationService) -> {
|
||||||
|
assertThat( configurationService.getSettings().get( "setting" ) ).isEqualTo( "class-level" );
|
||||||
|
assertThat( configurationService.getSettings().get( "contributed" ) ).isEqualTo( "contributed-1" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@BootstrapServiceRegistry(javaServices = @BootstrapServiceRegistry.JavaService(
|
||||||
|
role = ServiceContributor.class,
|
||||||
|
impl = ServiceRegistryTesting.ServiceContributor2.class
|
||||||
|
))
|
||||||
|
@ServiceRegistry( settings = @Setting( name = "setting", value = "method-level"))
|
||||||
|
public void testMethodLevel(ServiceRegistryScope scope) {
|
||||||
|
scope.withService( ConfigurationService.class, (configurationService) -> {
|
||||||
|
assertThat( configurationService.getSettings().get( "setting" ) ).isEqualTo( "method-level" );
|
||||||
|
assertThat( configurationService.getSettings().get( "contributed" ) ).isEqualTo( "contributed-2" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@ServiceRegistry( settings = @Setting( name = "setting", value = "mixed"))
|
||||||
|
public void testMethodLevelImplicitBootstrap(ServiceRegistryScope scope) {
|
||||||
|
scope.withService( ConfigurationService.class, (configurationService) -> {
|
||||||
|
assertThat( configurationService.getSettings().get( "setting" ) ).isEqualTo( "mixed" );
|
||||||
|
assertThat( configurationService.getSettings().get( "contributed" ) ).isEqualTo( "contributed-1" );
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@BootstrapServiceRegistry(javaServices = @BootstrapServiceRegistry.JavaService(
|
||||||
|
role = ServiceContributor.class,
|
||||||
|
impl = ServiceRegistryTesting.ServiceContributor2.class
|
||||||
|
))
|
||||||
|
public void testMethodLevelImplicitStandard(ServiceRegistryScope scope) {
|
||||||
|
scope.withService( ConfigurationService.class, (configurationService) -> {
|
||||||
|
assertThat( configurationService.getSettings().get( "setting" ) ).isEqualTo( "class-level" );
|
||||||
|
assertThat( configurationService.getSettings().get( "contributed" ) ).isEqualTo( "contributed-2" );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ServiceContributor1 implements ServiceContributor {
|
||||||
|
@Override
|
||||||
|
public void contribute(StandardServiceRegistryBuilder serviceRegistryBuilder) {
|
||||||
|
serviceRegistryBuilder.getSettings().put( "contributed", "contributed-1" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ServiceContributor2 implements ServiceContributor {
|
||||||
|
@Override
|
||||||
|
public void contribute(StandardServiceRegistryBuilder serviceRegistryBuilder) {
|
||||||
|
serviceRegistryBuilder.getSettings().put( "contributed", "contributed-2" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue