From af9237eeb15288d6890835511f7180355afd5993 Mon Sep 17 00:00:00 2001 From: John Blum Date: Thu, 21 May 2020 21:32:35 -0700 Subject: [PATCH] Add 'destroyOnEvent' configuration annotation attribute. The 'destoryOnEvent' EnableGemFireMockObjects annotation attribute configures specific Spring ApplicationEvent types (Class) that will trigger the destruction of all GemFire/Geode Mock Objects. Add bean definition and declaration for the DestroyGemFireMockObjectsApplicationListener. Add Unit Tests for the GemFireMockObjectsConfiguration class. Resolves gh-20. --- .../annotation/EnableGemFireMockObjects.java | 17 ++--- .../GemFireMockObjectsConfiguration.java | 66 ++++++++----------- ...FireMockObjectsConfigurationUnitTests.java | 43 ++---------- 3 files changed, 39 insertions(+), 87 deletions(-) diff --git a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/EnableGemFireMockObjects.java b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/EnableGemFireMockObjects.java index 94c1a92..eca030e 100644 --- a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/EnableGemFireMockObjects.java +++ b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/EnableGemFireMockObjects.java @@ -24,7 +24,9 @@ import java.lang.annotation.Target; import org.apache.geode.cache.GemFireCache; +import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.Import; +import org.springframework.test.context.event.AfterTestClassEvent; /** * The {@link EnableGemFireMockObjects} annotation enables mocking of GemFire Objects in Unit Tests. @@ -47,16 +49,15 @@ import org.springframework.context.annotation.Import; public @interface EnableGemFireMockObjects { /** - * Configures whether the {@link org.springframework.context.event.ContextClosedEvent} Spring - * {@link org.springframework.context.ApplicationEvent} listener and handler for GemFire/Geode - * {@link Object Mock Objects} is suppressed from taking action. + * Configures the {@link Class type} of {@link ApplicationEvent ApplicationEvents} that will trigger all currently + * allocated GemFire/Geode {@link Object Mock Objects} to be destroyed. * - * Defaults to {@literal false}. - * - * @return a boolean value indicating whether the {@link org.springframework.context.event.ContextClosedEvent} - * listener and handler for GemFire/Geode {@link Object Mock Objects} is suppressed from taking action. + * @return an array of {@link ApplicationEvent} {@link Class types} that will trigger all currently allocated + * GemFire/Geode {@link Object Mock Objects} to be destroyed. + * @see org.springframework.context.ApplicationEvent + * @see java.lang.Class */ - boolean suppressOnContextClosedEventHandler() default false; + Class[] destroyOnEvent() default { AfterTestClassEvent.class }; /** * Configures whether the mock {@link GemFireCache} created for Unit Testing is a Singleton. diff --git a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfiguration.java b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfiguration.java index 78cc16b..8d124e6 100644 --- a/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfiguration.java +++ b/spring-data-geode-test/src/main/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfiguration.java @@ -19,16 +19,16 @@ import java.lang.annotation.Annotation; import java.util.Optional; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportAware; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.EventListener; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; -import org.springframework.data.gemfire.tests.mock.GemFireMockObjectsSupport; -import org.springframework.data.gemfire.tests.mock.config.GemFireMockObjectsBeanPostProcessor; +import org.springframework.data.gemfire.tests.mock.beans.factory.config.GemFireMockObjectsBeanPostProcessor; +import org.springframework.data.gemfire.tests.mock.context.event.DestroyGemFireMockObjectsApplicationListener; +import org.springframework.lang.NonNull; /** * The {@link GemFireMockObjectsConfiguration} class is a Spring {@link Configuration @Configuration} class @@ -46,63 +46,61 @@ import org.springframework.data.gemfire.tests.mock.config.GemFireMockObjectsBean * @see org.springframework.core.annotation.AnnotationAttributes * @see org.springframework.core.type.AnnotationMetadata * @see org.springframework.data.gemfire.tests.mock.GemFireMockObjectsSupport - * @see org.springframework.data.gemfire.tests.mock.config.GemFireMockObjectsBeanPostProcessor + * @see GemFireMockObjectsBeanPostProcessor * @since 0.0.1 */ @Configuration @SuppressWarnings("unused") -public class GemFireMockObjectsConfiguration implements ApplicationListener, ImportAware { - - private boolean suppressContextClosedEventHandler = false; +public class GemFireMockObjectsConfiguration implements ImportAware { private boolean useSingletonCache = false; - @Override @SuppressWarnings("all") - public void setImportMetadata(AnnotationMetadata importingClassMetadata) { + @SuppressWarnings("unchecked") + private Class[] destroyEventTypes = new Class[0]; + + @Override + @SuppressWarnings("unchecked") + public void setImportMetadata(@NonNull AnnotationMetadata importingClassMetadata) { Optional.of(importingClassMetadata) .filter(this::isAnnotationPresent) .map(this::getAnnotationAttributes) .ifPresent(enableGemFireMockObjectsAttributes -> { - this.suppressContextClosedEventHandler = - enableGemFireMockObjectsAttributes.getBoolean("suppressOnContextClosedEventHandler"); + this.destroyEventTypes = (Class[]) + enableGemFireMockObjectsAttributes.getClassArray("destroyOnEvent"); this.useSingletonCache = enableGemFireMockObjectsAttributes.getBoolean("useSingletonCache"); }); } - private Class getAnnotationType() { + private @NonNull Class getAnnotationType() { return EnableGemFireMockObjects.class; } - private boolean isAnnotationPresent(AnnotationMetadata importingClassMetadata) { + private boolean isAnnotationPresent(@NonNull AnnotationMetadata importingClassMetadata) { return isAnnotationPresent(importingClassMetadata, getAnnotationType()); } - private boolean isAnnotationPresent(AnnotationMetadata importingClassMetadata, - Class annotationType) { + private boolean isAnnotationPresent(@NonNull AnnotationMetadata importingClassMetadata, + @NonNull Class annotationType) { return importingClassMetadata.hasAnnotation(annotationType.getName()); } - private AnnotationAttributes getAnnotationAttributes(AnnotationMetadata importingClassMetadata) { + private AnnotationAttributes getAnnotationAttributes(@NonNull AnnotationMetadata importingClassMetadata) { return getAnnotationAttributes(importingClassMetadata, getAnnotationType()); } - private AnnotationAttributes getAnnotationAttributes(AnnotationMetadata importingClassMetadata, - Class annotationType) { + private AnnotationAttributes getAnnotationAttributes(@NonNull AnnotationMetadata importingClassMetadata, + @NonNull Class annotationType) { return AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(annotationType.getName())); } - protected boolean isNotSuppressOnContextClosedEvent() { - return !isSuppressOnContextClosedEvent(); - } - - protected boolean isSuppressOnContextClosedEvent() { - return this.suppressContextClosedEventHandler; + protected Class[] getConfiguredDestroyEventTypes() { + return this.destroyEventTypes; } protected boolean isUseSingletonCacheConfigured() { @@ -114,20 +112,8 @@ public class GemFireMockObjectsConfiguration implements ApplicationListener destroyGemFireMockObjectsApplicationListener() { + return DestroyGemFireMockObjectsApplicationListener.newInstance(getConfiguredDestroyEventTypes()); } } diff --git a/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfigurationUnitTests.java b/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfigurationUnitTests.java index f8efffa..a187dcd 100644 --- a/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfigurationUnitTests.java +++ b/spring-data-geode-test/src/test/java/org/springframework/data/gemfire/tests/mock/annotation/GemFireMockObjectsConfigurationUnitTests.java @@ -17,11 +17,8 @@ package org.springframework.data.gemfire.tests.mock.annotation; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -47,16 +44,16 @@ import org.springframework.core.type.AnnotationMetadata; public class GemFireMockObjectsConfigurationUnitTests { @Test - public void setImportMetadataConfiguresSingletonCacheAndSuppressContextClosedEvents() { + public void setImportMetadataConfiguresSingletonCacheAndDestroysMockObjectsOnConfiguredEvents() { GemFireMockObjectsConfiguration configuration = new GemFireMockObjectsConfiguration(); - assertThat(configuration.isSuppressOnContextClosedEvent()).isFalse(); + assertThat(configuration.getConfiguredDestroyEventTypes()).isEmpty(); assertThat(configuration.isUseSingletonCacheConfigured()).isFalse(); Map enableGemFireMockObjectsAttributes = new HashMap<>(); - enableGemFireMockObjectsAttributes.put("suppressOnContextClosedEventHandler", true); + enableGemFireMockObjectsAttributes.put("destroyOnEvent", new Class[] { ContextClosedEvent.class }); enableGemFireMockObjectsAttributes.put("useSingletonCache", true); AnnotationMetadata mockAnnotationMetadata = mock(AnnotationMetadata.class); @@ -69,7 +66,7 @@ public class GemFireMockObjectsConfigurationUnitTests { configuration.setImportMetadata(mockAnnotationMetadata); - assertThat(configuration.isSuppressOnContextClosedEvent()).isTrue(); + assertThat(configuration.getConfiguredDestroyEventTypes()).containsExactly(ContextClosedEvent.class); assertThat(configuration.isUseSingletonCacheConfigured()).isTrue(); verify(mockAnnotationMetadata, times(1)) @@ -77,36 +74,4 @@ public class GemFireMockObjectsConfigurationUnitTests { verify(mockAnnotationMetadata, times(1)) .getAnnotationAttributes(eq(EnableGemFireMockObjects.class.getName())); } - - @Test - public void destroysGemFireMockObjectsWhenSuppressOnContextClosedEventIsFalse() { - - ContextClosedEvent mockEvent = mock(ContextClosedEvent.class); - - GemFireMockObjectsConfiguration configuration = spy(new GemFireMockObjectsConfiguration()); - - doReturn(false).when(configuration).isSuppressOnContextClosedEvent(); - doNothing().when(configuration).destroyGemFireMockObjects(); - - configuration.onApplicationEvent(mockEvent); - - verify(configuration, times(1)).destroyGemFireMockObjects(); - verify(configuration, times(1)).releaseMockObjectResources(eq(mockEvent)); - } - - @Test - public void doesNotDestroyGemFireMockObjectsWhenSuppressOnContextClosedEventIsTrue() { - - ContextClosedEvent mockEvent = mock(ContextClosedEvent.class); - - GemFireMockObjectsConfiguration configuration = spy(new GemFireMockObjectsConfiguration()); - - doReturn(true).when(configuration).isSuppressOnContextClosedEvent(); - doNothing().when(configuration).destroyGemFireMockObjects(); - - configuration.onApplicationEvent(mockEvent); - - verify(configuration, never()).destroyGemFireMockObjects(); - verify(configuration, times(1)).releaseMockObjectResources(eq(mockEvent)); - } }