GH-1110 - Register AssertablePublishedEvents in ApplicationContext if AssertJ is on the classpath.

We now check for the presence of AssertJ on the classpath and rather register an instance of ApplicationPublishedEvents in the ApplicationContext if present.
This commit is contained in:
Oliver Drotbohm
2025-03-17 19:01:53 +01:00
parent 8df778b039
commit 433a22559e
4 changed files with 72 additions and 9 deletions

View File

@@ -84,7 +84,7 @@ class ModuleContextCustomizerFactory implements ContextCustomizerFactory {
beanFactory.registerSingleton(ModuleTestExecutionBeanDefinitionSelector.class.getName(),
new ModuleTestExecutionBeanDefinitionSelector(testExecution));
var events = new DefaultPublishedEvents();
var events = PublishedEventsFactory.createPublishedEvents();
beanFactory.registerSingleton(events.getClass().getName(), events);
context.addApplicationListener(events);
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2025 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
*
* https://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.modulith.test;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.util.ClassUtils;
/**
* Creates an instance of {@link PublishedEvents} or {@link AssertablePublishedEvents} depending on whether AssertJ is
* on the classpath or not.
*
* @author Oliver Drotbohm
* @since 1.4
*/
class PublishedEventsFactory {
private static final boolean ASSERT_J_PRESENT = ClassUtils.isPresent("org.assertj.core.api.Assert",
PublishedEventsParameterResolver.class.getClassLoader());
/**
* Returns whether AssertJ is present or not.
*/
static boolean isAssertJPresent() {
return ASSERT_J_PRESENT;
}
/**
* Creates a instance of {@link PublishedEvents} that's also an {@link ApplicationListener} for
* {@link ApplicationEvent}s.
*
* @return will never be {@literal null}.
*/
@SuppressWarnings("unchecked")
static <T extends PublishedEvents & ApplicationListener<ApplicationEvent>> T createPublishedEvents() {
return (T) (isAssertJPresent() ? new DefaultAssertablePublishedEvents() : new DefaultPublishedEvents());
}
}

View File

@@ -27,7 +27,6 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Provides instances of {@link PublishedEvents} as test method parameters.
@@ -36,9 +35,6 @@ import org.springframework.util.ClassUtils;
*/
class PublishedEventsParameterResolver implements ParameterResolver, AfterEachCallback {
private static final boolean ASSERT_J_PRESENT = ClassUtils.isPresent("org.assertj.core.api.Assert",
PublishedEventsParameterResolver.class.getClassLoader());
private ThreadBoundApplicationListenerAdapter listener;
private final Function<ExtensionContext, ApplicationContext> lookup;
@@ -59,7 +55,8 @@ class PublishedEventsParameterResolver implements ParameterResolver, AfterEachCa
var type = parameterContext.getParameter().getType();
if (type.getName().equals("org.springframework.modulith.test.AssertablePublishedEvents") && !ASSERT_J_PRESENT) {
if (type.getName().equals("org.springframework.modulith.test.AssertablePublishedEvents")
&& !PublishedEventsFactory.isAssertJPresent()) {
throw new IllegalStateException(
"Method declares AssertablePublishedEvents as parameter but AssertJ is not on the classpath!");
}
@@ -74,9 +71,7 @@ class PublishedEventsParameterResolver implements ParameterResolver, AfterEachCa
@Override
public PublishedEvents resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
var publishedEvents = ASSERT_J_PRESENT
? new DefaultAssertablePublishedEvents()
: new DefaultPublishedEvents();
var publishedEvents = PublishedEventsFactory.createPublishedEvents();
initializeListener(extensionContext);
listener.registerDelegate(publishedEvents);

View File

@@ -21,9 +21,12 @@ import example.module.SampleTestA;
import example.module.SampleTestB;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.modulith.core.ApplicationModule;
import org.springframework.modulith.core.ApplicationModuleIdentifier;
import org.springframework.modulith.test.ModuleContextCustomizerFactory.ModuleContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
/**
* Unit tests for {@link ModuleTypeExcludeFilter}.
@@ -65,4 +68,18 @@ class ModuleContextCustomizerUnitTests {
assertThat(right).isEqualTo(left);
assertThat(left).hasSameHashCodeAs(right);
}
@Test // GH-1110
void registersAssertablePublishedEvents() {
var context = new AnnotationConfigApplicationContext();
var loader = new AnnotationConfigContextLoader();
new ModuleContextCustomizer(SampleTestA.class)
.customizeContext(context, new MergedContextConfiguration(SampleTestA.class, null, null, null, loader));
assertThat(context.getApplicationListeners()).hasSize(1)
.element(0)
.isInstanceOf(AssertablePublishedEvents.class);
}
}