HHH-15344 - Ability to apply testing annotations at method-level

- `@DomainModel`
This commit is contained in:
Steve Ebersole 2022-06-16 03:24:52 -05:00
parent 6c461a3674
commit 763d1764cd
21 changed files with 248 additions and 79 deletions

View File

@ -18,8 +18,8 @@
* Used to define the bootstrap ServiceRegistry to be used for testing. * Used to define the bootstrap ServiceRegistry to be used for testing.
*/ */
@Inherited @Inherited
@Target( ElementType.TYPE ) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention( RetentionPolicy.RUNTIME ) @Retention(RetentionPolicy.RUNTIME)
@ServiceRegistryFunctionalTesting @ServiceRegistryFunctionalTesting
public @interface BootstrapServiceRegistry { public @interface BootstrapServiceRegistry {

View File

@ -12,8 +12,6 @@
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.boot.model.TypeContributor; import org.hibernate.boot.model.TypeContributor;
import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.AccessType;
@ -22,6 +20,8 @@
import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.persistence.SharedCacheMode;
/** /**
* @asciidoc * @asciidoc
* *
@ -81,7 +81,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Inherited @Inherited
@Target(ElementType.TYPE) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@TestInstance( TestInstance.Lifecycle.PER_CLASS ) @TestInstance( TestInstance.Lifecycle.PER_CLASS )

View File

@ -26,7 +26,7 @@
import org.hibernate.testing.orm.domain.DomainModelDescriptor; import org.hibernate.testing.orm.domain.DomainModelDescriptor;
import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.domain.StandardDomainModel;
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;
@ -44,22 +44,67 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DomainModelExtension public class DomainModelExtension
implements TestInstancePostProcessor, AfterAllCallback, TestExecutionExceptionHandler { implements TestInstancePostProcessor, BeforeEachCallback, TestExecutionExceptionHandler {
private static final String MODEL_KEY = MetadataImplementor.class.getName(); private static final String MODEL_KEY = MetadataImplementor.class.getName();
@Override
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
assert context.getTestClass().isPresent();
final Optional<DomainModel> domainModelAnnRef = AnnotationSupport.findAnnotation(
context.getElement().get(),
DomainModel.class
);
if ( domainModelAnnRef.isPresent()
|| DomainModelProducer.class.isAssignableFrom( context.getRequiredTestClass() ) ) {
final DomainModelScope created = createDomainModelScope( testInstance, domainModelAnnRef, context );
locateExtensionStore( testInstance, context ).put( MODEL_KEY, created );
}
}
@Override
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(
context.getElement().get(),
DomainModel.class
);
if ( domainModelAnnRef.isEmpty() ) {
// assume the annotations are defined on the class-level...
// will be validated by the parameter-resolver or SFS-extension
return;
}
final DomainModelScope created = createDomainModelScope( context.getRequiredTestInstance(), domainModelAnnRef, context );
final ExtensionContext.Store extensionStore = locateExtensionStore( context.getRequiredTestInstance(), context );
extensionStore.put( MODEL_KEY, created );
}
@Override
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
final ExtensionContext.Store store = locateExtensionStore( context.getRequiredTestInstance(), context );
final DomainModelScopeImpl scope = (DomainModelScopeImpl) store.get( MODEL_KEY );
if ( scope != null ) {
scope.releaseModel();
}
throw throwable;
}
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( ServiceRegistryExtension.class, context, testInstance );
} }
public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) { private static DomainModelScope createDomainModelScope(
final ExtensionContext.Store store = locateExtensionStore( testInstance, context ); Object testInstance, Optional<DomainModel> domainModelAnnRef,
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY ); ExtensionContext context) {
if ( existing != null ) {
return existing;
}
final ServiceRegistryScope serviceRegistryScope = ServiceRegistryExtension.findServiceRegistryScope( final ServiceRegistryScope serviceRegistryScope = ServiceRegistryExtension.findServiceRegistryScope(
testInstance, testInstance,
context context
@ -71,21 +116,14 @@ public static DomainModelScope findDomainModelScope(Object testInstance, Extensi
modelProducer = (DomainModelProducer) testInstance; modelProducer = (DomainModelProducer) testInstance;
} }
else { else {
assert domainModelAnnRef != null && domainModelAnnRef.isPresent();
modelProducer = serviceRegistry -> { modelProducer = serviceRegistry -> {
if ( !context.getElement().isPresent() ) { if ( context.getElement().isEmpty() ) {
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<DomainModel> domainModelAnnotationWrapper = AnnotationSupport.findAnnotation( final DomainModel domainModelAnnotation = domainModelAnnRef.get();
context.getElement().get(),
DomainModel.class
);
if ( !domainModelAnnotationWrapper.isPresent() ) {
throw new RuntimeException( "Could not locate @DomainModel annotation : " + context.getDisplayName() );
}
final DomainModel domainModelAnnotation = domainModelAnnotationWrapper.get();
final MetadataSources metadataSources = new MetadataSources( serviceRegistry ); final MetadataSources metadataSources = new MetadataSources( serviceRegistry );
final ManagedBeanRegistry managedBeanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); final ManagedBeanRegistry managedBeanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
@ -108,7 +146,7 @@ public static DomainModelScope findDomainModelScope(Object testInstance, Extensi
} }
} }
for ( Class annotatedClass : domainModelAnnotation.annotatedClasses() ) { for ( Class<?> annotatedClass : domainModelAnnotation.annotatedClasses() ) {
metadataSources.addAnnotatedClass( annotatedClass ); metadataSources.addAnnotatedClass( annotatedClass );
} }
@ -157,12 +195,34 @@ public static DomainModelScope findDomainModelScope(Object testInstance, Extensi
( (DomainModelScopeAware) testInstance ).injectTestModelScope( scope ); ( (DomainModelScopeAware) testInstance ).injectTestModelScope( scope );
} }
locateExtensionStore( testInstance, context ).put( MODEL_KEY, scope );
return scope; return scope;
} }
protected static final void applyCacheSettings(Metadata metadata, boolean overrideCacheStrategy, String cacheConcurrencyStrategy) { public static DomainModelScope findDomainModelScope(Object testInstance, ExtensionContext context) {
// todo : allow for method-level
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
final DomainModelScope existing = (DomainModelScope) store.get( MODEL_KEY );
if ( existing != null ) {
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() );
}
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) {
if ( !overrideCacheStrategy ) { if ( !overrideCacheStrategy ) {
return; return;
} }
@ -178,9 +238,9 @@ protected static final void applyCacheSettings(Metadata metadata, boolean overri
boolean hasLob = false; boolean hasLob = false;
final Iterator props = entityBinding.getPropertyClosureIterator(); final Iterator<Property> props = entityBinding.getPropertyClosureIterator();
while ( props.hasNext() ) { while ( props.hasNext() ) {
final Property prop = (Property) props.next(); final Property prop = props.next();
if ( prop.getValue().isSimpleValue() ) { if ( prop.getValue().isSimpleValue() ) {
if ( isLob( (SimpleValue) prop.getValue() ) ) { if ( isLob( (SimpleValue) prop.getValue() ) ) {
hasLob = true; hasLob = true;
@ -226,33 +286,6 @@ private static boolean isLob(SimpleValue value) {
return false; return false;
} }
@Override
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
findDomainModelScope( testInstance, context );
}
@Override
public void afterAll(ExtensionContext context) {
final ExtensionContext.Store store = locateExtensionStore( context.getRequiredTestInstance(), context );
final DomainModelScopeImpl scope = (DomainModelScopeImpl) store.remove( MODEL_KEY );
if ( scope != null ) {
scope.close();
}
}
@Override
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
final ExtensionContext.Store store = locateExtensionStore( context.getRequiredTestInstance(), context );
final DomainModelScopeImpl scope = (DomainModelScopeImpl) store.get( MODEL_KEY );
if ( scope != null ) {
scope.releaseModel();
}
throw throwable;
}
public static class DomainModelScopeImpl implements DomainModelScope, ExtensionContext.Store.CloseableResource { public static class DomainModelScopeImpl implements DomainModelScope, ExtensionContext.Store.CloseableResource {
private final ServiceRegistryScope serviceRegistryScope; private final ServiceRegistryScope serviceRegistryScope;
private final DomainModelProducer producer; private final DomainModelProducer producer;

View File

@ -20,13 +20,10 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@TestInstance( TestInstance.Lifecycle.PER_CLASS ) @TestInstance( TestInstance.Lifecycle.PER_CLASS )
//@ExtendWith( ServiceRegistryExtension.class )
//@ExtendWith( ServiceRegistryParameterResolver.class )
@ServiceRegistryFunctionalTesting @ServiceRegistryFunctionalTesting
@ExtendWith( ExpectedExceptionExtension.class ) @ExtendWith( ExpectedExceptionExtension.class )

View File

@ -13,7 +13,6 @@
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
/** /**
@ -24,7 +23,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Inherited @Inherited
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Repeatable( FailureExpectedGroup.class ) @Repeatable( FailureExpectedGroup.class )

View File

@ -12,14 +12,13 @@
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Inherited @Inherited
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ExtendWith( FailureExpectedExtension.class ) @ExtendWith( FailureExpectedExtension.class )

View File

@ -32,7 +32,7 @@
* @author Chris Cranford * @author Chris Cranford
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target({ElementType.TYPE, ElementType.METHOD})
@Inherited @Inherited
@TestInstance(TestInstance.Lifecycle.PER_CLASS ) @TestInstance(TestInstance.Lifecycle.PER_CLASS )
@ExtendWith(EntityManagerFactoryScopeExtension.class) @ExtendWith(EntityManagerFactoryScopeExtension.class)

View File

@ -23,7 +23,7 @@
* better option. * better option.
*/ */
@Inherited @Inherited
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ExtendWith( LoggingInspectionsExtension.class ) @ExtendWith( LoggingInspectionsExtension.class )

View File

@ -20,7 +20,7 @@
* For watching a multiple message-keys, see {@link LoggingInspections} * For watching a multiple message-keys, see {@link LoggingInspections}
*/ */
@Inherited @Inherited
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.METHOD }) @Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ExtendWith( MessageKeyInspectionExtension.class ) @ExtendWith( MessageKeyInspectionExtension.class )

View File

@ -25,7 +25,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@Repeatable( RequiresDialects.class ) @Repeatable( RequiresDialects.class )
@ExtendWith( DialectFilterExtension.class ) @ExtendWith( DialectFilterExtension.class )

View File

@ -23,7 +23,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ ElementType.TYPE, ElementType.METHOD})
@Repeatable( RequiresDialectFeatureGroup.class ) @Repeatable( RequiresDialectFeatureGroup.class )
@ExtendWith( DialectFilterExtension.class ) @ExtendWith( DialectFilterExtension.class )

View File

@ -22,7 +22,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ ElementType.TYPE, ElementType.METHOD})
@ExtendWith( DialectFilterExtension.class ) @ExtendWith( DialectFilterExtension.class )
public @interface RequiresDialectFeatureGroup { public @interface RequiresDialectFeatureGroup {

View File

@ -19,7 +19,7 @@
*/ */
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Target({ ElementType.TYPE, ElementType.METHOD})
@ExtendWith( DialectFilterExtension.class ) @ExtendWith( DialectFilterExtension.class )
public @interface RequiresDialects { public @interface RequiresDialects {

View File

@ -62,7 +62,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Inherited @Inherited
@Target( ElementType.TYPE ) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@ServiceRegistryFunctionalTesting @ServiceRegistryFunctionalTesting

View File

@ -23,7 +23,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@TestInstance( TestInstance.Lifecycle.PER_CLASS ) @TestInstance( TestInstance.Lifecycle.PER_CLASS )

View File

@ -23,7 +23,7 @@
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Inherited @Inherited
@Target( ElementType.TYPE ) @Target({ElementType.TYPE, ElementType.METHOD})
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@TestInstance( TestInstance.Lifecycle.PER_CLASS ) @TestInstance( TestInstance.Lifecycle.PER_CLASS )

View File

@ -33,7 +33,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@TestInstance( TestInstance.Lifecycle.PER_CLASS ) @TestInstance( TestInstance.Lifecycle.PER_CLASS )

View File

@ -29,7 +29,7 @@
*/ */
@Inherited @Inherited
@Retention( RetentionPolicy.RUNTIME ) @Retention( RetentionPolicy.RUNTIME )
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Target({ElementType.TYPE, ElementType.METHOD})
@Repeatable( SkipForDialectGroup.class ) @Repeatable( SkipForDialectGroup.class )
@ExtendWith( DialectFilterExtension.class ) @ExtendWith( DialectFilterExtension.class )

View File

@ -0,0 +1,43 @@
/*
* 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;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
/**
* @author Steve Ebersole
*/
@Entity
public class AnotherEntity {
@Id
private Integer id;
@Basic
private String name;
private AnotherEntity() {
// for Hibernate use
}
public AnotherEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.spi.MetadataImplementor;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.testing.annotations.AnEntity;
import org.hibernate.testing.annotations.AnotherEntity;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.DomainModelScope;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
@ServiceRegistry( settings = @Setting( name = "simple", value = "simple-value"))
@DomainModel( annotatedClasses = AnEntity.class )
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class DomainModelTesting {
private int executingTestOrder;
@Test
@Order( 2 )
public void testClassLevelAnnotations(DomainModelScope scope) {
executingTestOrder = 2;
classLevelAssertions( scope );
}
private void classLevelAssertions(DomainModelScope scope) {
assertThat( scope.getDomainModel().getEntityBinding( AnEntity.class.getName() ) ).isNotNull();
assertThat( scope.getDomainModel().getEntityBinding( AnotherEntity.class.getName() ) ).isNull();
settingAssertions( scope );
}
private void settingAssertions(DomainModelScope scope) {
final org.hibernate.service.ServiceRegistry serviceRegistry = ( (MetadataImplementor) scope.getDomainModel() )
.getTypeConfiguration()
.getServiceRegistry();
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
assertThat( configurationService.getSettings().get( "simple" ) ).isEqualTo( "simple-value" );
}
@Test
@DomainModel( annotatedClasses = AnotherEntity.class )
@Order( 1 )
public void testMethodLevelAnnotations(DomainModelScope scope) {
executingTestOrder = 1;
methodLevelAssertions( scope );
}
private void methodLevelAssertions(DomainModelScope scope) {
assertThat( scope.getDomainModel().getEntityBinding( AnEntity.class.getName() ) ).isNull();
assertThat( scope.getDomainModel().getEntityBinding( AnotherEntity.class.getName() ) ).isNotNull();
settingAssertions( scope );
}
@AfterEach
public void doStuffAfter(DomainModelScope scope) {
if ( executingTestOrder == 1 ) {
methodLevelAssertions( scope );
}
else if ( executingTestOrder == 2 ) {
classLevelAssertions( scope );
}
else {
throw new RuntimeException( "boom" );
}
}
}

View File

@ -0,0 +1,15 @@
/*
* 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.
*/
/**
* Testing the ability to apply testing annotations at method-level
*
* See https://hibernate.atlassian.net/browse/HHH-15344
*
* @author Steve Ebersole
*/
package org.hibernate.testing.annotations.methods;