Skip to content

Commit f805d09

Browse files
committed
Fix trouble with Webflux tests on Spring Boot 4.0
1 parent 227ab7d commit f805d09

File tree

5 files changed

+328
-0
lines changed

5 files changed

+328
-0
lines changed

integration/spring-data/testsuite/webflux/pom.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,32 @@
602602
<scope>test</scope>
603603
</dependency>
604604
</dependencies>
605+
<build>
606+
<plugins>
607+
<plugin>
608+
<groupId>org.codehaus.mojo</groupId>
609+
<artifactId>build-helper-maven-plugin</artifactId>
610+
<executions>
611+
<execution>
612+
<id>add-test-source</id>
613+
<phase>generate-test-sources</phase>
614+
<goals>
615+
<goal>add-test-source</goal>
616+
</goals>
617+
<configuration>
618+
<sources>
619+
<!--
620+
Spring Boot 4 moved the WebFluxTest annotation to a separate package of a different module,
621+
so to avoid copying tests, we copied the WebFluxTest handling of Spring Boot 4.0
622+
-->
623+
<source>${project.basedir}/src/test/spring4</source>
624+
</sources>
625+
</configuration>
626+
</execution>
627+
</executions>
628+
</plugin>
629+
</plugins>
630+
</build>
605631
</profile>
606632
</profiles>
607633
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.web.reactive;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Inherited;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
26+
import org.junit.jupiter.api.extension.ExtendWith;
27+
28+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
29+
import org.springframework.boot.autoconfigure.SpringBootApplication;
30+
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
31+
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson;
32+
import org.springframework.boot.test.context.SpringBootTest;
33+
import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters;
34+
import org.springframework.boot.webflux.test.autoconfigure.AutoConfigureWebFlux;
35+
import org.springframework.boot.webtestclient.autoconfigure.AutoConfigureWebTestClient;
36+
import org.springframework.context.annotation.ComponentScan;
37+
import org.springframework.context.annotation.Import;
38+
import org.springframework.core.annotation.AliasFor;
39+
import org.springframework.core.env.Environment;
40+
import org.springframework.test.context.BootstrapWith;
41+
import org.springframework.test.context.junit.jupiter.SpringExtension;
42+
import org.springframework.test.web.reactive.server.WebTestClient;
43+
44+
/**
45+
* Annotation that can be used for a Spring WebFlux test that focuses
46+
* <strong>only</strong> on Spring WebFlux components.
47+
* <p>
48+
* Using this annotation only enables auto-configuration that is relevant to WebFlux
49+
* tests. Similarly, component scanning is limited to beans annotated with:
50+
* <ul>
51+
* <li>{@code @Controller}</li>
52+
* <li>{@code @ControllerAdvice}</li>
53+
* <li>{@code @JacksonComponent}</li>
54+
* <li>{@code @JsonComponent} (Jackson 2, deprecated)</li>
55+
* </ul>
56+
* <p>
57+
* as well as beans that implement:
58+
* <ul>
59+
* <li>{@code Converter}</li>
60+
* <li>{@code GenericConverter}</li>
61+
* <li>{@code IDialect}, if Thymeleaf is available</li>
62+
* <li>{@code JacksonModule}, if Jackson is available</li>
63+
* <li>{@code Module}, if Jackson 2 is available (deprecated)</li>
64+
* <li>{@code WebExceptionHandler}</li>
65+
* <li>{@code WebFluxConfigurer}</li>
66+
* <li>{@code WebFilter}</li>
67+
* </ul>
68+
* <p>
69+
* By default, tests annotated with {@code @WebFluxTest} will also auto-configure a
70+
* {@link WebTestClient}. For more fine-grained control of WebTestClient the
71+
* {@link AutoConfigureWebTestClient @AutoConfigureWebTestClient} annotation can be used.
72+
* <p>
73+
* Typically {@code @WebFluxTest} is used in combination with
74+
* {@link org.springframework.test.context.bean.override.mockito.MockitoBean @MockitoBean}
75+
* or {@link Import @Import} to create any collaborators required by your
76+
* {@code @Controller} beans.
77+
* <p>
78+
* If you are looking to load your full application configuration and use WebTestClient,
79+
* you should consider {@link SpringBootTest @SpringBootTest} combined with
80+
* {@link AutoConfigureWebTestClient @AutoConfigureWebTestClient} rather than this
81+
* annotation.
82+
* <p>
83+
* When using JUnit 4, this annotation should be used in combination with
84+
* {@code @RunWith(SpringRunner.class)}.
85+
*
86+
* @author Stephane Nicoll
87+
* @author Artsiom Yudovin
88+
* @since 4.0.0
89+
* @see AutoConfigureWebFlux
90+
* @see AutoConfigureWebTestClient
91+
*/
92+
@Target(ElementType.TYPE)
93+
@Retention(RetentionPolicy.RUNTIME)
94+
@Documented
95+
@Inherited
96+
@BootstrapWith(WebFluxTestContextBootstrapper.class)
97+
@ExtendWith(SpringExtension.class)
98+
@OverrideAutoConfiguration(enabled = false)
99+
@TypeExcludeFilters(WebFluxTypeExcludeFilter.class)
100+
@AutoConfigureJson
101+
@AutoConfigureWebFlux
102+
@AutoConfigureWebTestClient
103+
@ImportAutoConfiguration
104+
public @interface WebFluxTest {
105+
106+
/**
107+
* Properties in form {@literal key=value} that should be added to the Spring
108+
* {@link Environment} before the test runs.
109+
* @return the properties to add
110+
*/
111+
String[] properties() default {};
112+
113+
/**
114+
* Specifies the controllers to test. This is an alias of {@link #controllers()} which
115+
* can be used for brevity if no other attributes are defined. See
116+
* {@link #controllers()} for details.
117+
* @see #controllers()
118+
* @return the controllers to test
119+
*/
120+
@AliasFor("controllers")
121+
Class<?>[] value() default {};
122+
123+
/**
124+
* Specifies the controllers to test. May be left blank if all {@code @Controller}
125+
* beans should be added to the application context.
126+
* @see #value()
127+
* @return the controllers to test
128+
*/
129+
@AliasFor("value")
130+
Class<?>[] controllers() default {};
131+
132+
/**
133+
* Determines if default filtering should be used with
134+
* {@link SpringBootApplication @SpringBootApplication}. By default only
135+
* {@code @Controller} (when no explicit {@link #controllers() controllers} are
136+
* defined), {@code @ControllerAdvice} and {@code WebFluxConfigurer} beans are
137+
* included.
138+
* @see #includeFilters()
139+
* @see #excludeFilters()
140+
* @return if default filters should be used
141+
*/
142+
boolean useDefaultFilters() default true;
143+
144+
/**
145+
* A set of include filters which can be used to add otherwise filtered beans to the
146+
* application context.
147+
* @return include filters to apply
148+
*/
149+
ComponentScan.Filter[] includeFilters() default {};
150+
151+
/**
152+
* A set of exclude filters which can be used to filter beans that would otherwise be
153+
* added to the application context.
154+
* @return exclude filters to apply
155+
*/
156+
ComponentScan.Filter[] excludeFilters() default {};
157+
158+
/**
159+
* Auto-configuration exclusions that should be applied for this test.
160+
* @return auto-configuration exclusions to apply
161+
*/
162+
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
163+
Class<?>[] excludeAutoConfiguration() default {};
164+
165+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.autoconfigure.web.reactive;
18+
19+
import org.springframework.boot.test.autoconfigure.TestSliceTestContextBootstrapper;
20+
import org.springframework.boot.test.context.ReactiveWebMergedContextConfiguration;
21+
import org.springframework.test.context.MergedContextConfiguration;
22+
import org.springframework.test.context.TestContextBootstrapper;
23+
24+
/**
25+
* {@link TestContextBootstrapper} for {@link WebFluxTest @WebFluxTest} support.
26+
*
27+
* @author Stephane Nicoll
28+
* @author Artsiom Yudovin
29+
*/
30+
class WebFluxTestContextBootstrapper extends TestSliceTestContextBootstrapper<WebFluxTest> {
31+
32+
@Override
33+
protected MergedContextConfiguration processMergedContextConfiguration(MergedContextConfiguration mergedConfig) {
34+
return new ReactiveWebMergedContextConfiguration(super.processMergedContextConfiguration(mergedConfig));
35+
}
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2012-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.boot.test.autoconfigure.web.reactive;
17+
18+
import java.util.Arrays;
19+
import java.util.Collections;
20+
import java.util.LinkedHashSet;
21+
import java.util.Set;
22+
23+
import org.springframework.boot.context.TypeExcludeFilter;
24+
import org.springframework.boot.test.context.filter.annotation.StandardAnnotationCustomizableTypeExcludeFilter;
25+
import org.springframework.core.convert.converter.Converter;
26+
import org.springframework.core.convert.converter.GenericConverter;
27+
import org.springframework.stereotype.Controller;
28+
import org.springframework.util.ClassUtils;
29+
import org.springframework.util.ObjectUtils;
30+
import org.springframework.web.bind.annotation.ControllerAdvice;
31+
import org.springframework.web.reactive.config.WebFluxConfigurer;
32+
import org.springframework.web.server.WebExceptionHandler;
33+
import org.springframework.web.server.WebFilter;
34+
35+
/**
36+
* {@link TypeExcludeFilter} for {@link WebFluxTest @WebFluxTest}.
37+
*
38+
* @author Stephane Nicoll
39+
*/
40+
class WebFluxTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<WebFluxTest> {
41+
42+
private static final Class<?>[] NO_CONTROLLERS = {};
43+
44+
private static final String[] OPTIONAL_INCLUDES = { "tools.jackson.databind.JacksonModule",
45+
"org.springframework.boot.jackson.JacksonComponent", "com.fasterxml.jackson.databind.Module",
46+
"org.springframework.boot.jackson2.JsonComponent" };
47+
48+
private static final Set<Class<?>> KNOWN_INCLUDES;
49+
50+
static {
51+
Set<Class<?>> includes = new LinkedHashSet<>();
52+
includes.add(ControllerAdvice.class);
53+
includes.add(WebFluxConfigurer.class);
54+
includes.add(Converter.class);
55+
includes.add(GenericConverter.class);
56+
includes.add(WebExceptionHandler.class);
57+
includes.add(WebFilter.class);
58+
for (String optionalInclude : OPTIONAL_INCLUDES) {
59+
try {
60+
includes.add(ClassUtils.forName(optionalInclude, null));
61+
}
62+
catch (Exception ex) {
63+
// Ignore
64+
}
65+
}
66+
KNOWN_INCLUDES = Collections.unmodifiableSet(includes);
67+
}
68+
69+
private static final Set<Class<?>> KNOWN_INCLUDES_AND_CONTROLLER;
70+
71+
static {
72+
Set<Class<?>> includes = new LinkedHashSet<>(KNOWN_INCLUDES);
73+
includes.add(Controller.class);
74+
KNOWN_INCLUDES_AND_CONTROLLER = Collections.unmodifiableSet(includes);
75+
}
76+
77+
private final Class<?>[] controllers;
78+
79+
WebFluxTypeExcludeFilter(Class<?> testClass) {
80+
super(testClass);
81+
this.controllers = getAnnotation().getValue("controllers", Class[].class).orElse(NO_CONTROLLERS);
82+
}
83+
84+
@Override
85+
protected Set<Class<?>> getKnownIncludes() {
86+
if (ObjectUtils.isEmpty(this.controllers)) {
87+
return KNOWN_INCLUDES_AND_CONTROLLER;
88+
}
89+
return KNOWN_INCLUDES;
90+
}
91+
92+
@Override
93+
protected Set<Class<?>> getComponentIncludes() {
94+
return new LinkedHashSet<>(Arrays.asList(this.controllers));
95+
}
96+
97+
}

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<!-- Plugin versions -->
3333
<version.antrun.plugin>3.1.0</version.antrun.plugin>
3434
<version.assembly.plugin>3.6.0</version.assembly.plugin>
35+
<version.buildhelper.plugin>3.6.1</version.buildhelper.plugin>
3536
<version.checkstyle.plugin>3.6.0</version.checkstyle.plugin>
3637
<version.clean.plugin>3.3.1</version.clean.plugin>
3738
<version.compiler.plugin>3.13.0</version.compiler.plugin>
@@ -250,6 +251,8 @@
250251
<exclude>**/src/test/java/com/blazebit/persistence/view/processor/model/**</exclude>
251252
<exclude>**/src/test/java/javax/annotation/**</exclude>
252253
<exclude>**/jpa-3.2-compatibility/src/main/java/module-info.java</exclude>
254+
255+
<exclude>**/src/test/spring4/org/springframework/boot/test/autoconfigure/web/reactive/**</exclude>
253256
</excludes>
254257
</configuration>
255258
<executions>

0 commit comments

Comments
 (0)