Skip to content

Commit ec2957a

Browse files
committed
Test for supportsEventType mismatch with unrelated event type
See gh-30712
1 parent d3df45d commit ec2957a

File tree

1 file changed

+114
-10
lines changed

1 file changed

+114
-10
lines changed

spring-context/src/test/java/org/springframework/context/event/ApplicationListenerMethodAdapterTests.java

Lines changed: 114 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.lang.reflect.Method;
2121
import java.lang.reflect.UndeclaredThrowableException;
22+
import java.util.List;
2223

2324
import org.junit.jupiter.api.Test;
2425

@@ -46,6 +47,8 @@
4647

4748
/**
4849
* @author Stephane Nicoll
50+
* @author Juergen Hoeller
51+
* @author Simon Baslé
4952
*/
5053
public class ApplicationListenerMethodAdapterTests extends AbstractApplicationEventListenerTests {
5154

@@ -80,16 +83,23 @@ public void genericListenerWrongParameterizedType() {
8083
supportsEventType(false, method, ResolvableType.forClassWithGenerics(GenericTestEvent.class, Long.class));
8184
}
8285

86+
@Test
87+
public void genericListenerWithUnresolvedGenerics() {
88+
Method method = ReflectionUtils.findMethod(
89+
SampleEvents.class, "handleGenericString", GenericTestEvent.class);
90+
supportsEventType(true, method, ResolvableType.forClass(GenericTestEvent.class));
91+
}
92+
8393
@Test
8494
public void listenerWithPayloadAndGenericInformation() {
8595
Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class);
86-
supportsEventType(true, method, createGenericEventType(String.class));
96+
supportsEventType(true, method, createPayloadEventType(String.class));
8797
}
8898

8999
@Test
90100
public void listenerWithInvalidPayloadAndGenericInformation() {
91101
Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleString", String.class);
92-
supportsEventType(false, method, createGenericEventType(Integer.class));
102+
supportsEventType(false, method, createPayloadEventType(Integer.class));
93103
}
94104

95105
@Test
@@ -113,28 +123,28 @@ public void listenerWithSubTypeSeveralGenericsResolved() {
113123
@Test
114124
public void listenerWithAnnotationValue() {
115125
Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringAnnotationValue");
116-
supportsEventType(true, method, createGenericEventType(String.class));
126+
supportsEventType(true, method, createPayloadEventType(String.class));
117127
}
118128

119129
@Test
120130
public void listenerWithAnnotationClasses() {
121131
Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringAnnotationClasses");
122-
supportsEventType(true, method, createGenericEventType(String.class));
132+
supportsEventType(true, method, createPayloadEventType(String.class));
123133
}
124134

125135
@Test
126136
public void listenerWithAnnotationValueAndParameter() {
127137
Method method = ReflectionUtils.findMethod(
128138
SampleEvents.class, "handleStringAnnotationValueAndParameter", String.class);
129-
supportsEventType(true, method, createGenericEventType(String.class));
139+
supportsEventType(true, method, createPayloadEventType(String.class));
130140
}
131141

132142
@Test
133143
public void listenerWithSeveralTypes() {
134144
Method method = ReflectionUtils.findMethod(SampleEvents.class, "handleStringOrInteger");
135-
supportsEventType(true, method, createGenericEventType(String.class));
136-
supportsEventType(true, method, createGenericEventType(Integer.class));
137-
supportsEventType(false, method, createGenericEventType(Double.class));
145+
supportsEventType(true, method, createPayloadEventType(String.class));
146+
supportsEventType(true, method, createPayloadEventType(Integer.class));
147+
supportsEventType(false, method, createPayloadEventType(Double.class));
138148
}
139149

140150
@Test
@@ -325,6 +335,88 @@ public void beanInstanceRetrievedAtEveryInvocation() {
325335
verify(this.context, times(2)).getBean("testBean");
326336
}
327337

338+
@Test // gh-30399
339+
void simplePayloadDoesNotSupportArbitraryGenericEventType() throws Exception {
340+
Method method = SampleEvents.class.getDeclaredMethod("handleString", String.class);
341+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
342+
343+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(EntityWrapper.class, Integer.class))))
344+
.as("handleString(String) with EntityWrapper<Integer>").isFalse();
345+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClass(EntityWrapper.class))))
346+
.as("handleString(String) with EntityWrapper<?>").isFalse();
347+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClass(String.class))))
348+
.as("handleString(String) with String").isTrue();
349+
}
350+
351+
@Test // gh-30399
352+
void genericPayloadDoesNotSupportArbitraryGenericEventType() throws Exception {
353+
Method method = SampleEvents.class.getDeclaredMethod("handleGenericStringPayload", EntityWrapper.class);
354+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
355+
356+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClass(EntityWrapper.class))))
357+
.as("handleGenericStringPayload(EntityWrapper<String>) with EntityWrapper<?>").isFalse();
358+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(EntityWrapper.class, Integer.class))))
359+
.as("handleGenericStringPayload(EntityWrapper<String>) with EntityWrapper<Integer>").isFalse();
360+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(EntityWrapper.class, String.class))))
361+
.as("handleGenericStringPayload(EntityWrapper<String>) with EntityWrapper<String>").isTrue();
362+
}
363+
364+
@Test // gh-30399
365+
void rawGenericPayloadDoesNotSupportArbitraryGenericEventType() throws Exception {
366+
Method method = SampleEvents.class.getDeclaredMethod("handleGenericAnyPayload", EntityWrapper.class);
367+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
368+
369+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClass(EntityWrapper.class))))
370+
.as("handleGenericAnyPayload(EntityWrapper<?>) with EntityWrapper<?>").isTrue();
371+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(EntityWrapper.class, Integer.class))))
372+
.as("handleGenericAnyPayload(EntityWrapper<?>) with EntityWrapper<Integer>").isTrue();
373+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(EntityWrapper.class, String.class))))
374+
.as("handleGenericAnyPayload(EntityWrapper<?>) with EntityWrapper<String>").isTrue();
375+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClass(List.class))))
376+
.as("handleGenericAnyPayload(EntityWrapper<?>) with List<?>").isFalse();
377+
assertThat(adapter.supportsEventType(createPayloadEventType(ResolvableType.forClassWithGenerics(List.class, String.class))))
378+
.as("handleGenericAnyPayload(EntityWrapper<?>) with List<String>").isFalse();
379+
}
380+
381+
@Test // gh-30399
382+
void genericApplicationEventSupportsSpecificType() throws Exception {
383+
Method method = SampleEvents.class.getDeclaredMethod("handleGenericString", GenericTestEvent.class);
384+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
385+
386+
assertThat(adapter.supportsEventType(ResolvableType.forClass(GenericTestEvent.class)))
387+
.as("handleGenericString(GenericTestEvent<String>) with GenericTestEvent<?>").isTrue();
388+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, Integer.class)))
389+
.as("handleGenericString(GenericTestEvent<String>) with GenericTestEvent<Integer>").isFalse();
390+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, String.class)))
391+
.as("handleGenericString(GenericTestEvent<String>) with GenericTestEvent<String>").isTrue();
392+
}
393+
394+
@Test // gh-30399
395+
void genericRawApplicationEventSupportsRawTypeAndAnySpecificType() throws Exception {
396+
Method method = SampleEvents.class.getDeclaredMethod("handleGenericRaw", GenericTestEvent.class);
397+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
398+
399+
assertThat(adapter.supportsEventType(ResolvableType.forClass(GenericTestEvent.class)))
400+
.as("handleGenericRaw(GenericTestEvent<?>) with GenericTestEvent<?>").isTrue();
401+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, String.class)))
402+
.as("handleGenericRaw(GenericTestEvent<?>) with GenericTestEvent<String>").isTrue();
403+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, Integer.class)))
404+
.as("handleGenericRaw(GenericTestEvent<?>) with GenericTestEvent<Integer>").isTrue();
405+
}
406+
407+
@Test // gh-30399
408+
void unrelatedApplicationEventDoesNotSupportRawTypeOrAnySpecificType() throws Exception {
409+
Method method = SampleEvents.class.getDeclaredMethod("handleUnrelated", ContextRefreshedEvent.class);
410+
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
411+
412+
assertThat(adapter.supportsEventType(ResolvableType.forClass(GenericTestEvent.class)))
413+
.as("handleUnrelated(ContextRefreshedEvent) with GenericTestEvent<?>").isTrue(); // known bug in 5.3.x
414+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, String.class)))
415+
.as("handleUnrelated(ContextRefreshedEvent) with GenericTestEvent<String>").isFalse();
416+
assertThat(adapter.supportsEventType(ResolvableType.forClassWithGenerics(GenericTestEvent.class, Integer.class)))
417+
.as("handleUnrelated(ContextRefreshedEvent) with GenericTestEvent<Integer>").isFalse();
418+
}
419+
328420

329421
private void supportsEventType(boolean match, Method method, ResolvableType eventType) {
330422
ApplicationListenerMethodAdapter adapter = createTestInstance(method);
@@ -341,7 +433,11 @@ private ApplicationListenerMethodAdapter createTestInstance(Method method) {
341433
return new StaticApplicationListenerMethodAdapter(method, this.sampleEvents);
342434
}
343435

344-
private ResolvableType createGenericEventType(Class<?> payloadType) {
436+
private ResolvableType createPayloadEventType(Class<?> payloadType) {
437+
return ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, payloadType);
438+
}
439+
440+
private ResolvableType createPayloadEventType(ResolvableType payloadType) {
345441
return ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, payloadType);
346442
}
347443

@@ -373,6 +469,14 @@ public void handleRaw(ApplicationEvent event) {
373469
public void handleGenericString(GenericTestEvent<String> event) {
374470
}
375471

472+
@EventListener
473+
public void handleGenericRaw(GenericTestEvent<?> event) {
474+
}
475+
476+
@EventListener
477+
public void handleUnrelated(ContextRefreshedEvent event) {
478+
}
479+
376480
@EventListener
377481
public void handleString(String payload) {
378482
}

0 commit comments

Comments
 (0)