/* * Copyright 2002-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.test.web.reactive.server; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.format.FormatterRegistry; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.validation.Validator; import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder; import org.springframework.web.reactive.config.CorsRegistry; import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration; import org.springframework.web.reactive.config.PathMatchConfigurer; import org.springframework.web.reactive.config.ViewResolverRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer; import org.springframework.web.server.adapter.WebHttpHandlerBuilder; /** * Default implementation of {@link WebTestClient.ControllerSpec}. * * @author Rossen Stoyanchev * @since 5.0 */ class DefaultControllerSpec extends AbstractMockServerSpec<WebTestClient.ControllerSpec> implements WebTestClient.ControllerSpec { private final List<Object> controllers; private final List<Object> controllerAdvice = new ArrayList<>(8); private final TestWebFluxConfigurer configurer = new TestWebFluxConfigurer(); DefaultControllerSpec(Object... controllers) { Assert.isTrue(!ObjectUtils.isEmpty(controllers), "At least one controller is required"); this.controllers = Arrays.asList(controllers); } @Override public DefaultControllerSpec controllerAdvice(Object... controllerAdvice) { this.controllerAdvice.addAll(Arrays.asList(controllerAdvice)); return this; } @Override public DefaultControllerSpec contentTypeResolver(Consumer<RequestedContentTypeResolverBuilder> consumer) { this.configurer.contentTypeResolverConsumer = consumer; return this; } @Override public DefaultControllerSpec corsMappings(Consumer<CorsRegistry> consumer) { this.configurer.corsRegistryConsumer = consumer; return this; } @Override public DefaultControllerSpec argumentResolvers(Consumer<ArgumentResolverConfigurer> consumer) { this.configurer.argumentResolverConsumer = consumer; return this; } @Override public DefaultControllerSpec pathMatching(Consumer<PathMatchConfigurer> consumer) { this.configurer.pathMatchConsumer = consumer; return this; } @Override public DefaultControllerSpec httpMessageCodecs(Consumer<ServerCodecConfigurer> consumer) { this.configurer.messageCodecsConsumer = consumer; return this; } @Override public DefaultControllerSpec formatters(Consumer<FormatterRegistry> consumer) { this.configurer.formattersConsumer = consumer; return this; } @Override public DefaultControllerSpec validator(Validator validator) { this.configurer.validator = validator; return this; } @Override public DefaultControllerSpec viewResolvers(Consumer<ViewResolverRegistry> consumer) { this.configurer.viewResolversConsumer = consumer; return this; } @Override protected WebHttpHandlerBuilder initHttpHandlerBuilder() { return WebHttpHandlerBuilder.applicationContext(initApplicationContext()); } private ApplicationContext initApplicationContext() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); this.controllers.forEach(controller -> { String name = controller.getClass().getName(); context.registerBean(name, Object.class, () -> controller); }); this.controllerAdvice.forEach(advice -> { String name = advice.getClass().getName(); context.registerBean(name, Object.class, () -> advice); }); context.register(DelegatingWebFluxConfiguration.class); context.registerBean(WebFluxConfigurer.class, () -> this.configurer); context.refresh(); return context; } private class TestWebFluxConfigurer implements WebFluxConfigurer { private Consumer<RequestedContentTypeResolverBuilder> contentTypeResolverConsumer; private Consumer<CorsRegistry> corsRegistryConsumer; private Consumer<ArgumentResolverConfigurer> argumentResolverConsumer; private Consumer<PathMatchConfigurer> pathMatchConsumer; private Consumer<ServerCodecConfigurer> messageCodecsConsumer; private Consumer<FormatterRegistry> formattersConsumer; private Validator validator; private Consumer<ViewResolverRegistry> viewResolversConsumer; @Override public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { if (this.contentTypeResolverConsumer != null) { this.contentTypeResolverConsumer.accept(builder); } } @Override public void addCorsMappings(CorsRegistry registry) { if (this.corsRegistryConsumer != null) { this.corsRegistryConsumer.accept(registry); } } @Override public void configurePathMatching(PathMatchConfigurer configurer) { if (this.pathMatchConsumer != null) { this.pathMatchConsumer.accept(configurer); } } @Override public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { if (this.argumentResolverConsumer != null) { this.argumentResolverConsumer.accept(configurer); } } @Override public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { if (this.messageCodecsConsumer != null) { this.messageCodecsConsumer.accept(configurer); } } @Override public void addFormatters(FormatterRegistry registry) { if (this.formattersConsumer != null) { this.formattersConsumer.accept(registry); } } @Override public Optional<Validator> getValidator() { return Optional.ofNullable(this.validator); } @Override public void configureViewResolvers(ViewResolverRegistry registry) { if (this.viewResolversConsumer != null) { this.viewResolversConsumer.accept(registry); } } } }