From 57f452fec19ab8bb3ce6b3c84d10cbae20bb7ad5 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 24 Jun 2024 10:55:02 -0700 Subject: [PATCH] Disable ReactorResourceFactory use of global resources in tests Add `ContextCustomizerFactory` to automatically disable the use of `ReactorResourceFactory` global resources in tests. Fixes gh-38199 --- ...ctoryGlobalResourcesBeanPostProcessor.java | 39 ++++++++++ ...obalResourcesContextCustomizerFactory.java | 74 +++++++++++++++++++ .../test/web/reactor/netty/package-info.java | 20 +++++ .../main/resources/META-INF/spring.factories | 3 +- ...esourcesContextCustomizerFactoryTests.java | 55 ++++++++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor.java create mode 100644 spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory.java create mode 100644 spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/package-info.java create mode 100644 spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactoryTests.java diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor.java new file mode 100644 index 00000000000..bd4b18e2889 --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2024 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.boot.test.web.reactor.netty; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.http.client.ReactorResourceFactory; + +/** + * {@link BeanPostProcessor} to disable the use of global resources in + * {@link ReactorResourceFactory} preventing test cleanup issues. + * + * @author Phillip Webb + */ +class DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof ReactorResourceFactory reactorResourceFactory) { + reactorResourceFactory.setUseGlobalResources(false); + } + return bean; + } + +} diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory.java new file mode 100644 index 00000000000..bcbfdd568e3 --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012-2024 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.boot.test.web.reactor.netty; + +import java.util.List; + +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.http.client.ReactorResourceFactory; +import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.util.ClassUtils; + +/** + * {@link ContextCustomizerFactory} to disable the use of global resources in + * {@link ReactorResourceFactory} preventing test cleanup issues. + * + * @author Phillip Webb + */ +class DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory implements ContextCustomizerFactory { + + String REACTOR_RESOURCE_FACTORY_CLASS = "org.springframework.http.client.ReactorResourceFactory"; + + @Override + public ContextCustomizer createContextCustomizer(Class testClass, + List configAttributes) { + if (ClassUtils.isPresent(this.REACTOR_RESOURCE_FACTORY_CLASS, testClass.getClassLoader())) { + return new DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer(); + } + return null; + + } + + static final class DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer + implements ContextCustomizer { + + private DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer() { + } + + @Override + public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) { + context.getBeanFactory() + .registerSingleton(DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor.class.getName(), + new DisableReactorResourceFactoryGlobalResourcesBeanPostProcessor()); + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof DisableReactorResourceFactoryGlobalResourcesContextCustomizerCustomizer); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/package-info.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/package-info.java new file mode 100644 index 00000000000..6580806accb --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/reactor/netty/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2024 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. + */ + +/** + * Spring Boot support for testing Reactor Netty. + */ +package org.springframework.boot.test.web.reactor.netty; diff --git a/spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring.factories index 57c2b6bda7f..24e84e5c8c8 100644 --- a/spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-test/src/main/resources/META-INF/spring.factories @@ -6,7 +6,8 @@ org.springframework.boot.test.graphql.tester.HttpGraphQlTesterContextCustomizerF org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory,\ org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory,\ org.springframework.boot.test.web.client.TestRestTemplateContextCustomizerFactory,\ -org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizerFactory +org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizerFactory,\ +org.springframework.boot.test.web.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory # Test Execution Listeners org.springframework.test.context.TestExecutionListener=\ diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactoryTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactoryTests.java new file mode 100644 index 00000000000..fab2b7f6d96 --- /dev/null +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/reactor/netty/DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactoryTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2024 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.boot.test.web.reactor.netty; + +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ReactorResourceFactory; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory}. + * + * @author Phillip Webb + */ +@SpringJUnitConfig +class DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactoryTests { + + @Autowired + private ReactorResourceFactory reactorResourceFactory; + + @Test + void disablesUseGlobalResources() { + assertThat(this.reactorResourceFactory.isUseGlobalResources()).isFalse(); + } + + @Configuration + static class Config { + + @Bean + ReactorResourceFactory reactorResourceFactory() { + return new ReactorResourceFactory(); + } + + } + +}