Add support for Mock test with WebFlux

This commit add mock support for WebFlux with an infrastructure similar
to what `WebMvcTest` provides. `@WebFluxTest` can be used to test
controllers with a narrowed classpath that is relevant to WebFlux. Also,
`@SpringBootTest` now starts WebFlux in "mock" mode by default and
`@AutoConfigureWebTestClient` can be used to inject a `WebTestClient`
connected to the `ApplicationContext`.

To make that happen, a `ReactiveWebApplicationContext` interface has been
introduced to mirror what `WebApplicationContext` currently does. Things
are still a bit volatile at this point and that infra may move to Spring
Framework at some point.

Closes gh-8401
pull/8198/merge
Stephane Nicoll 8 years ago
parent 30564eb619
commit c5595f296c

@ -19,7 +19,7 @@ package org.springframework.boot.autoconfigure.condition;
import java.util.Map;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.ReactiveWebApplicationContext;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.Ordered;

@ -21,7 +21,7 @@ import org.junit.Test;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.webflux.MockReactiveWebServerFactory;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.GenericReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.ReactiveWebServerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -64,7 +64,7 @@ public class ConditionalOnNotWebApplicationTests {
@Test
public void testNotWebApplicationWithReactiveContext() {
ReactiveWebApplicationContext ctx = new ReactiveWebApplicationContext();
GenericReactiveWebApplicationContext ctx = new GenericReactiveWebApplicationContext();
ctx.register(ReactiveApplicationConfig.class, NotWebApplicationConfiguration.class);
ctx.refresh();

@ -22,7 +22,7 @@ import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.webflux.MockReactiveWebServerFactory;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.GenericReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.ReactiveWebServerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -68,7 +68,7 @@ public class ConditionalOnWebApplicationTests {
@Test
public void testWebApplicationWithReactiveContext() {
ReactiveWebApplicationContext ctx = new ReactiveWebApplicationContext();
GenericReactiveWebApplicationContext ctx = new GenericReactiveWebApplicationContext();
ctx.register(AnyWebApplicationConfiguration.class,
ServletWebApplicationConfiguration.class,
ReactiveWebApplicationConfiguration.class);

@ -22,7 +22,7 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.ReactiveWebServerCustomizer;
import org.springframework.boot.context.embedded.ReactiveWebServerFactory;
import org.springframework.context.ApplicationContextException;
@ -40,14 +40,14 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class ReactiveWebServerAutoConfigurationTests {
private ReactiveWebApplicationContext context;
private EmbeddedReactiveWebApplicationContext context;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void createFromConfigClass() {
this.context = new ReactiveWebApplicationContext(BaseConfiguration.class);
this.context = new EmbeddedReactiveWebApplicationContext(BaseConfiguration.class);
assertThat(this.context.getBeansOfType(ReactiveWebServerFactory.class)).hasSize(1);
assertThat(this.context.getBeansOfType(ReactiveWebServerCustomizer.class)).hasSize(1);
@ -58,7 +58,7 @@ public class ReactiveWebServerAutoConfigurationTests {
public void missingHttpHandler() {
this.thrown.expect(ApplicationContextException.class);
this.thrown.expectMessage(Matchers.containsString("missing HttpHandler bean"));
this.context = new ReactiveWebApplicationContext(MissingHttpHandlerConfiguration.class);
this.context = new EmbeddedReactiveWebApplicationContext(MissingHttpHandlerConfiguration.class);
}
@Test
@ -66,12 +66,12 @@ public class ReactiveWebServerAutoConfigurationTests {
this.thrown.expect(ApplicationContextException.class);
this.thrown.expectMessage(Matchers
.containsString("multiple HttpHandler beans : httpHandler,additionalHttpHandler"));
this.context = new ReactiveWebApplicationContext(BaseConfiguration.class, TooManyHttpHandlers.class);
this.context = new EmbeddedReactiveWebApplicationContext(BaseConfiguration.class, TooManyHttpHandlers.class);
}
@Test
public void customizeReactiveWebServer() {
this.context = new ReactiveWebApplicationContext(BaseConfiguration.class,
this.context = new EmbeddedReactiveWebApplicationContext(BaseConfiguration.class,
ReactiveWebServerCustomization.class);
MockReactiveWebServerFactory factory = this.context.getBean(MockReactiveWebServerFactory.class);
assertThat(factory.getPort()).isEqualTo(9000);

@ -18,7 +18,7 @@ package org.springframework.boot.autoconfigure.webflux;
import org.junit.Test;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedReactiveWebApplicationContext;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.Bean;
@ -58,7 +58,7 @@ import static org.mockito.Mockito.mock;
*/
public class WebFluxAnnotationAutoConfigurationTests {
private ReactiveWebApplicationContext context;
private EmbeddedReactiveWebApplicationContext context;
@Test
public void shouldNotProcessIfExistingHttpHandler() throws Exception {
@ -173,7 +173,7 @@ public class WebFluxAnnotationAutoConfigurationTests {
}
private void load(Class<?> config, String... environment) {
this.context = new ReactiveWebApplicationContext();
this.context = new EmbeddedReactiveWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment);
this.context.register(config);
if (!config.equals(BaseConfiguration.class)) {

@ -20,7 +20,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedReactiveWebApplicationContext;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.ApplicationContextException;
@ -50,7 +50,7 @@ public class WebFluxFunctionalAutoConfigurationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private ReactiveWebApplicationContext context;
private EmbeddedReactiveWebApplicationContext context;
@Test
public void shouldNotProcessIfExistingHttpHandler() throws Exception {
@ -92,7 +92,7 @@ public class WebFluxFunctionalAutoConfigurationTests {
private void load(Class<?> config, String... environment) {
this.context = new ReactiveWebApplicationContext();
this.context = new EmbeddedReactiveWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, environment);
this.context.register(config);
if (!config.equals(BaseConfiguration.class)) {

@ -100,6 +100,11 @@
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>

@ -0,0 +1,44 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
/**
* {@link ImportAutoConfiguration Auto-configuration imports} for typical Spring WebFlux
* tests. Most tests should consider using {@link WebFluxTest @WebFluxTest} rather than
* using this annotation directly.
*
* @author Stephane Nicoll
* @since 2.0.0
* @see WebFluxTest
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
public @interface AutoConfigureWebFlux {
}

@ -0,0 +1,43 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.test.web.reactive.server.WebTestClient;
/**
* Annotation that can be applied to a test class to enable a {@link WebTestClient}.
*
* @author Stephane Nicoll
* @since 2.0.0
* @see WebTestClientAutoConfiguration
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
public @interface AutoConfigureWebTestClient {
}

@ -0,0 +1,132 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache;
import org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.BootstrapWith;
import org.springframework.test.web.reactive.server.WebTestClient;
/**
* Annotation that can be used in combination with {@code @RunWith(SpringRunner.class)}
* for a typical Spring WebFlux test. Can be used when a test focuses
* <strong>only</strong> on Spring WebFlux components.
* <p>
* Using this annotation will disable full auto-configuration and instead apply only
* configuration relevant to WebFlux tests (i.e. {@code @Controller},
* {@code @ControllerAdvice}, {@code @JsonComponent} and {@code WebFluxConfigurer} beans
* but not {@code @Component}, {@code @Service} or {@code @Repository} beans).
* <p>
* By default, tests annotated with {@code @WebFluxTest} will also auto-configure a
* {@link WebTestClient}. For more fine-grained control of WebTestClient the
* {@link AutoConfigureWebTestClient @AutoConfigureWebTestClient} annotation can be used.
* <p>
* Typically {@code @WebFluxTest} is used in combination with {@link MockBean @MockBean} or
* {@link Import @Import} to create any collaborators required by your {@code @Controller}
* beans.
* <p>
* If you are looking to load your full application configuration and use WebTestClient,
* you should consider {@link SpringBootTest @SpringBootTest} combined with
* {@link AutoConfigureWebTestClient @AutoConfigureWebTestClient} rather than this
* annotation.
*
* @author Stephane Nicoll
* @since 2.0.0
* @see AutoConfigureWebFlux
* @see AutoConfigureWebTestClient
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(WebFluxTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(WebFluxTypeExcludeFilter.class)
@AutoConfigureCache
@AutoConfigureWebFlux
@AutoConfigureWebTestClient
@ImportAutoConfiguration
public @interface WebFluxTest {
/**
* Specifies the controllers to test. This is an alias of {@link #controllers()} which
* can be used for brevity if no other attributes are defined. See
* {@link #controllers()} for details.
* @see #controllers()
* @return the controllers to test
*/
@AliasFor("controllers")
Class<?>[] value() default {};
/**
* Specifies the controllers to test. May be left blank if all {@code @Controller}
* beans should be added to the application context.
* @see #value()
* @return the controllers to test
*/
@AliasFor("value")
Class<?>[] controllers() default {};
/**
* Determines if default filtering should be used with
* {@link SpringBootApplication @SpringBootApplication}. By default only
* {@code @Controller} (when no explicit {@link #controllers() controllers} are
* defined), {@code @ControllerAdvice} and {@code WebFluxConfigurer} beans are
* included.
* @see #includeFilters()
* @see #excludeFilters()
* @return if default filters should be used
*/
boolean useDefaultFilters() default true;
/**
* A set of include filters which can be used to add otherwise filtered beans to the
* application context.
* @return include filters to apply
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* A set of exclude filters which can be used to filter beans that would otherwise be
* added to the application context.
* @return exclude filters to apply
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Auto-configuration exclusions that should be applied for this test.
* @return auto-configuration exclusions to apply
*/
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
Class<?>[] excludeAutoConfiguration() default {};
}

@ -0,0 +1,38 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.springframework.boot.test.context.ReactiveWebMergedContextConfiguration;
import org.springframework.boot.test.context.SpringBootTestContextBootstrapper;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextBootstrapper;
/**
* {@link TestContextBootstrapper} for {@link WebFluxTest @WebFluxTest} support.
*
* @author Stephane Nicoll
*/
class WebFluxTestContextBootstrapper extends SpringBootTestContextBootstrapper {
@Override
protected MergedContextConfiguration processMergedContextConfiguration(
MergedContextConfiguration mergedConfig) {
return new ReactiveWebMergedContextConfiguration(
super.processMergedContextConfiguration(mergedConfig));
}
}

@ -0,0 +1,100 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.test.autoconfigure.filter.AnnotationCustomizableTypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.reactive.config.WebFluxConfigurer;
/**
* {@link TypeExcludeFilter} for {@link WebFluxTest @WebFluxTest}.
*
* @author Stephane Nicoll
*/
class WebFluxTypeExcludeFilter extends AnnotationCustomizableTypeExcludeFilter {
private static final Set<Class<?>> DEFAULT_INCLUDES;
static {
Set<Class<?>> includes = new LinkedHashSet<Class<?>>();
includes.add(ControllerAdvice.class);
includes.add(JsonComponent.class);
includes.add(WebFluxConfigurer.class);
DEFAULT_INCLUDES = Collections.unmodifiableSet(includes);
}
private static final Set<Class<?>> DEFAULT_INCLUDES_AND_CONTROLLER;
static {
Set<Class<?>> includes = new LinkedHashSet<Class<?>>(DEFAULT_INCLUDES);
includes.add(Controller.class);
DEFAULT_INCLUDES_AND_CONTROLLER = Collections.unmodifiableSet(includes);
}
private final WebFluxTest annotation;
WebFluxTypeExcludeFilter(Class<?> testClass) {
this.annotation = AnnotatedElementUtils.getMergedAnnotation(testClass,
WebFluxTest.class);
}
@Override
protected boolean hasAnnotation() {
return this.annotation != null;
}
@Override
protected ComponentScan.Filter[] getFilters(FilterType type) {
switch (type) {
case INCLUDE:
return this.annotation.includeFilters();
case EXCLUDE:
return this.annotation.excludeFilters();
}
throw new IllegalStateException("Unsupported type " + type);
}
@Override
protected boolean isUseDefaultFilters() {
return this.annotation.useDefaultFilters();
}
@Override
protected Set<Class<?>> getDefaultIncludes() {
if (ObjectUtils.isEmpty(this.annotation.controllers())) {
return DEFAULT_INCLUDES_AND_CONTROLLER;
}
return DEFAULT_INCLUDES;
}
@Override
protected Set<Class<?>> getComponentIncludes() {
return new LinkedHashSet<>(Arrays.asList(this.annotation.controllers()));
}
}

@ -0,0 +1,42 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Auto-configuration for {@link WebTestClient}.
*
* @author Stephane Nicoll
*/
@Configuration
@ConditionalOnClass({ WebClient.class, WebTestClient.class })
public class WebTestClientAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public WebTestClient webTestClient(ApplicationContext applicationContext) {
return WebTestClient.bindToApplicationContext(applicationContext).build();
}
}

@ -46,6 +46,16 @@ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters=\
org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration
# AutoConfigureWebClient auto-configuration imports
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient=\
org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration
# AutoConfigureWebFlux auto-configuration imports
org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebFlux=\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.webflux.WebFluxAnnotationAutoConfiguration
# AutoConfigureMockMvc auto-configuration imports
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=\
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,\

@ -0,0 +1,38 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Example {@link Controller} used with {@link WebFluxTest} tests.
*
* @author Stephane Nicoll
*/
@RestController
public class ExampleController1 {
@GetMapping("/one")
public Mono<String> one() {
return Mono.just("one");
}
}

@ -0,0 +1,38 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import reactor.core.publisher.Mono;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Example {@link Controller} used with {@link WebFluxTest} tests.
*
* @author Stephane Nicoll
*/
@RestController
public class ExampleController2 {
@GetMapping("/two")
public Mono<String> two() {
return Mono.just("two");
}
}

@ -0,0 +1,28 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.springframework.stereotype.Service;
/**
* Example {@link Service} used with {@link WebFluxTest} tests.
*
* @author Stephane Nicoll
*/
@Service
public class ExampleRealService {
}

@ -0,0 +1,28 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Example {@link SpringBootApplication} used with {@link WebFluxTest} tests.
*
* @author Stephane Nicoll
*/
@SpringBootApplication
public class ExampleWebFluxApplication {
}

@ -0,0 +1,56 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
/**
* Tests for {@link WebFluxTest} when no explicit controller is defined.
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@WebFluxTest
public class WebFluxTestAllControllersIntegrationTests {
@Autowired
private WebTestClient webClient;
@Test
public void shouldFindController1() {
this.webClient
.get().uri("/one")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).value().isEqualTo("one");
}
@Test
public void shouldFindController2() {
this.webClient
.get().uri("/two")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).value().isEqualTo("two");
}
}

@ -0,0 +1,54 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.autoconfigure.AutoConfigurationImportedCondition.importedAutoConfiguration;
/**
* Tests for the auto-configuration imported by {@link WebFluxTest}.
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@WebFluxTest
public class WebFluxTestAutoConfigurationIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
public void messageSourceAutoConfigurationIsImported() {
assertThat(this.applicationContext)
.has(importedAutoConfiguration(MessageSourceAutoConfiguration.class));
}
@Test
public void validationAutoConfigurationIsImported() {
assertThat(this.applicationContext)
.has(importedAutoConfiguration(ValidationAutoConfiguration.class));
}
}

@ -0,0 +1,50 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link WebFluxTest} and {@link MessageSource} auto-configuration.
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@WebFluxTest
@TestPropertySource(properties = "spring.messages.basename=web-test-messages")
public class WebFluxTestMessageSourceIntegrationTests {
@Autowired
private ApplicationContext context;
@Test
public void messageSourceHasBeenAutoConfigured() {
assertThat(this.context.getMessage("a", null, Locale.ENGLISH)).isEqualTo("alpha");
}
}

@ -0,0 +1,55 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
/**
* Tests for {@link WebFluxTest} when a specific controller is defined.
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@WebFluxTest(controllers = ExampleController1.class)
public class WebFluxTestOneControllerIntegrationTests {
@Autowired
private WebTestClient webClient;
@Test
public void shouldFindController() {
this.webClient
.get().uri("/one")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).value().isEqualTo("one");
}
@Test
public void shouldNotScanOtherController() {
this.webClient
.get().uri("/two")
.exchange()
.expectStatus().isNotFound();
}
}

@ -0,0 +1,167 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import java.io.IOException;
import org.junit.Test;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link WebFluxTypeExcludeFilter}.
*
* @author Phillip Webb
* @author Stephane Nicoll
*/
public class WebFluxTypeExcludeFilterTests {
private MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
@Test
public void matchWhenHasNoControllers() throws Exception {
WebFluxTypeExcludeFilter filter = new WebFluxTypeExcludeFilter(
WithNoControllers.class);
assertThat(excludes(filter, Controller1.class)).isFalse();
assertThat(excludes(filter, Controller2.class)).isFalse();
assertThat(excludes(filter, ExampleControllerAdvice.class)).isFalse();
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
assertThat(excludes(filter, ExampleService.class)).isTrue();
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
}
@Test
public void matchWhenHasController() throws Exception {
WebFluxTypeExcludeFilter filter = new WebFluxTypeExcludeFilter(
WithController.class);
assertThat(excludes(filter, Controller1.class)).isFalse();
assertThat(excludes(filter, Controller2.class)).isTrue();
assertThat(excludes(filter, ExampleControllerAdvice.class)).isFalse();
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
assertThat(excludes(filter, ExampleService.class)).isTrue();
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
}
@Test
public void matchNotUsingDefaultFilters() throws Exception {
WebFluxTypeExcludeFilter filter = new WebFluxTypeExcludeFilter(
NotUsingDefaultFilters.class);
assertThat(excludes(filter, Controller1.class)).isTrue();
assertThat(excludes(filter, Controller2.class)).isTrue();
assertThat(excludes(filter, ExampleControllerAdvice.class)).isTrue();
assertThat(excludes(filter, ExampleWeb.class)).isTrue();
assertThat(excludes(filter, ExampleService.class)).isTrue();
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
}
@Test
public void matchWithIncludeFilter() throws Exception {
WebFluxTypeExcludeFilter filter = new WebFluxTypeExcludeFilter(
WithIncludeFilter.class);
assertThat(excludes(filter, Controller1.class)).isFalse();
assertThat(excludes(filter, Controller2.class)).isFalse();
assertThat(excludes(filter, ExampleControllerAdvice.class)).isFalse();
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
assertThat(excludes(filter, ExampleService.class)).isTrue();
assertThat(excludes(filter, ExampleRepository.class)).isFalse();
}
@Test
public void matchWithExcludeFilter() throws Exception {
WebFluxTypeExcludeFilter filter = new WebFluxTypeExcludeFilter(
WithExcludeFilter.class);
assertThat(excludes(filter, Controller1.class)).isTrue();
assertThat(excludes(filter, Controller2.class)).isFalse();
assertThat(excludes(filter, ExampleControllerAdvice.class)).isFalse();
assertThat(excludes(filter, ExampleWeb.class)).isFalse();
assertThat(excludes(filter, ExampleService.class)).isTrue();
assertThat(excludes(filter, ExampleRepository.class)).isTrue();
}
private boolean excludes(WebFluxTypeExcludeFilter filter, Class<?> type)
throws IOException {
MetadataReader metadataReader = this.metadataReaderFactory
.getMetadataReader(type.getName());
return filter.match(metadataReader, this.metadataReaderFactory);
}
@WebFluxTest
static class WithNoControllers {
}
@WebFluxTest(Controller1.class)
static class WithController {
}
@WebFluxTest(useDefaultFilters = false)
static class NotUsingDefaultFilters {
}
@WebFluxTest(includeFilters = @Filter(Repository.class))
static class WithIncludeFilter {
}
@WebFluxTest(excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = Controller1.class))
static class WithExcludeFilter {
}
@Controller
static class Controller1 {
}
@Controller
static class Controller2 {
}
@ControllerAdvice
static class ExampleControllerAdvice {
}
static class ExampleWeb implements WebFluxConfigurer {
}
@Service
static class ExampleService {
}
@Repository
static class ExampleRepository {
}
}

@ -0,0 +1,71 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.test.autoconfigure.web.reactive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpringBootTest} with {@link AutoConfigureWebTestClient} (i.e. full
* integration test).
*
* @author Stephane Nicoll
*/
@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.main.web-application-type=reactive")
@AutoConfigureWebTestClient
public class WebTestClientSpringBootTestIntegrationTests {
@Autowired
private WebTestClient webClient;
@Autowired
private ApplicationContext applicationContext;
@Test
public void shouldFindController1() {
this.webClient
.get().uri("/one")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).value().isEqualTo("one");
}
@Test
public void shouldFindController2() {
this.webClient
.get().uri("/two")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).value().isEqualTo("two");
}
@Test
public void shouldHaveRealService() throws Exception {
assertThat(this.applicationContext.getBeansOfType(ExampleRealService.class))
.hasSize(1);
}
}

@ -36,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@RunWith(SpringRunner.class)
@WebMvcTest(secure = false)
@TestPropertySource(properties = "spring.messages.basename=web-mvc-test-messages")
@TestPropertySource(properties = "spring.messages.basename=web-test-messages")
public class WebMvcTestMessageSourceIntegrationTests {
@Autowired

@ -23,10 +23,11 @@ import org.springframework.test.context.MergedContextConfiguration;
* all of its superclasses for a reactive web application.
*
* @author Stephane Nicoll
* @since 2.0.0
*/
class ReactiveWebMergedContextConfiguration extends MergedContextConfiguration {
public class ReactiveWebMergedContextConfiguration extends MergedContextConfiguration {
ReactiveWebMergedContextConfiguration(
public ReactiveWebMergedContextConfiguration(
MergedContextConfiguration mergedConfig) {
super(mergedConfig);
}

@ -28,6 +28,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.GenericReactiveWebApplicationContext;
import org.springframework.boot.test.mock.web.SpringBootMockServletContext;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.support.ServletContextApplicationContextInitializer;
@ -116,6 +117,9 @@ public class SpringBootContextLoader extends AbstractContextLoader {
}
else if (config instanceof ReactiveWebMergedContextConfiguration) {
application.setWebApplicationType(WebApplicationType.REACTIVE);
if (!isEmbeddedWebEnvironment(config)) {
new ReactiveWebConfigurer().configure(application);
}
}
else {
application.setWebApplicationType(WebApplicationType.NONE);
@ -281,6 +285,19 @@ public class SpringBootContextLoader extends AbstractContextLoader {
}
/**
* Inner class to configure {@link ReactiveWebMergedContextConfiguration}.
*/
private static class ReactiveWebConfigurer {
private static final Class<GenericReactiveWebApplicationContext> WEB_CONTEXT_CLASS = GenericReactiveWebApplicationContext.class;
void configure(SpringApplication application) {
application.setApplicationContextClass(WEB_CONTEXT_CLASS);
}
}
/**
* Adapts a {@link ContextCustomizer} to a {@link ApplicationContextInitializer} so
* that it can be triggered via {@link SpringApplication}.

@ -164,8 +164,8 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr
mergedConfig = new WebMergedContextConfiguration(mergedConfig,
resourceBasePath);
}
else if (webApplicationType == WebApplicationType.REACTIVE
&& webEnvironment.isEmbedded()) {
else if (webApplicationType == WebApplicationType.REACTIVE &&
(webEnvironment.isEmbedded() || webEnvironment == WebEnvironment.MOCK)) {
return new ReactiveWebMergedContextConfiguration(mergedConfig);
}
}

@ -21,8 +21,8 @@ import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.ReactiveWebServerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatReactiveWebServerFactory;
import org.springframework.context.ApplicationContext;

@ -182,7 +182,7 @@ public class SpringApplication {
* reactive web environments.
*/
public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework."
+ "boot.context.embedded.ReactiveWebApplicationContext";
+ "boot.context.embedded.EmbeddedReactiveWebApplicationContext";
private static final String REACTIVE_WEB_ENVIRONMENT_CLASS = "org.springframework."
+ "web.reactive.DispatcherHandler";

@ -0,0 +1,40 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.context;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Subclass of {@link AnnotationConfigApplicationContext}, suitable for reactive web
* environments.
*
* @author Stephane Nicoll
* @since 2.0.0
*/
public class GenericReactiveWebApplicationContext
extends AnnotationConfigApplicationContext
implements ReactiveWebApplicationContext {
public GenericReactiveWebApplicationContext() {
super();
}
public GenericReactiveWebApplicationContext(Class<?>[] annotatedClasses) {
super(annotatedClasses);
}
}

@ -0,0 +1,29 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.context;
import org.springframework.context.ApplicationContext;
/**
* Interface to provide configuration for a reactive web application.
*
* @author Stephane Nicoll
* @since 2.0.0
*/
public interface ReactiveWebApplicationContext extends ApplicationContext {
}

@ -17,27 +17,28 @@
package org.springframework.boot.context.embedded;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.GenericReactiveWebApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.StringUtils;
/**
* A {@link AnnotationConfigApplicationContext} that can be used to bootstrap
* A {@link GenericReactiveWebApplicationContext} that can be used to bootstrap
* itself from a contained embedded web server factory bean.
*
* @author Brian Clozel
* @since 2.0.0
*/
public class ReactiveWebApplicationContext extends AnnotationConfigApplicationContext {
public class EmbeddedReactiveWebApplicationContext
extends GenericReactiveWebApplicationContext {
private volatile EmbeddedWebServer embeddedWebServer;
public ReactiveWebApplicationContext() {
public EmbeddedReactiveWebApplicationContext() {
super();
}
public ReactiveWebApplicationContext(Class... annotatedClasses) {
public EmbeddedReactiveWebApplicationContext(Class... annotatedClasses) {
super(annotatedClasses);
}

@ -17,7 +17,7 @@
package org.springframework.boot.context.embedded;
/**
* Event to be published after the {@link ReactiveWebApplicationContext} is
* Event to be published after the {@link EmbeddedReactiveWebApplicationContext} is
* refreshed and the {@link EmbeddedWebServer} is ready. Useful for
* obtaining the local port of a running server.
*
@ -27,17 +27,17 @@ package org.springframework.boot.context.embedded;
*/
public class EmbeddedReactiveWebServerInitializedEvent extends EmbeddedWebServerInitializedEvent {
private final ReactiveWebApplicationContext applicationContext;
private final EmbeddedReactiveWebApplicationContext applicationContext;
public EmbeddedReactiveWebServerInitializedEvent(
EmbeddedWebServer source,
ReactiveWebApplicationContext applicationContext) {
EmbeddedReactiveWebApplicationContext applicationContext) {
super(source);
this.applicationContext = applicationContext;
}
@Override
public ReactiveWebApplicationContext getApplicationContext() {
public EmbeddedReactiveWebApplicationContext getApplicationContext() {
return this.applicationContext;
}

@ -44,7 +44,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedReactiveWebApplicationContext;
import org.springframework.boot.context.embedded.reactor.ReactorNettyReactiveWebServerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
@ -406,7 +406,7 @@ public class SpringApplicationTests {
SpringApplication application = new SpringApplication(ExampleReactiveWebConfig.class);
application.setWebApplicationType(WebApplicationType.REACTIVE);
this.context = application.run();
assertThat(this.context).isInstanceOf(ReactiveWebApplicationContext.class);
assertThat(this.context).isInstanceOf(EmbeddedReactiveWebApplicationContext.class);
}
@Test

Loading…
Cancel
Save