From d80a5e0427645c2dc29b014fe2557b41dc7f3b21 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Tue, 13 May 2025 20:03:19 +0200 Subject: [PATCH] Add tests for AutoConfigurations and LoadBalancerUriTools. Signed-off-by: Olga Maciaszek-Sharma --- .../loadbalancer/LoadBalancerUriTools.java | 3 + ...actLoadBalancerAutoConfigurationTests.java | 158 ++++++++++-------- .../LoadBalancerUriToolsTests.java | 87 +++++++--- ...dBalancerClientAutoConfigurationTests.java | 50 ++++-- 4 files changed, 200 insertions(+), 98 deletions(-) diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriTools.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriTools.java index 22a48f48..9f687b39 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriTools.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriTools.java @@ -126,6 +126,9 @@ public final class LoadBalancerUriTools { } public static boolean isServiceIdUrl(String baseUrlString, String serviceId) { + if (serviceId == null) { + return false; + } if (baseUrlString == null) { return false; } diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java index 2a387edd..8b8333ec 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/AbstractLoadBalancerAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -25,9 +25,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.http.client.service.HttpClientServiceProperties; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.client.DefaultServiceInstance; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerWebClientHttpServiceGroupConfigurer; import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -48,110 +50,127 @@ import static org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoa public abstract class AbstractLoadBalancerAutoConfigurationTests { protected ApplicationContextRunner applicationContextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(LoadBalancerAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(LoadBalancerAutoConfiguration.class)); @Test void restTemplateGetsLoadBalancerInterceptor() { - applicationContextRunner.withUserConfiguration(OneRestTemplate.class).run(context -> { - final Map restTemplates = context.getBeansOfType(RestTemplate.class); + applicationContextRunner.withUserConfiguration(OneRestTemplate.class) + .run(context -> { + final Map restTemplates = context.getBeansOfType(RestTemplate.class); - then(restTemplates).isNotNull(); - then(restTemplates.values()).hasSize(1); - RestTemplate restTemplate = restTemplates.values().iterator().next(); - then(restTemplate).isNotNull(); + then(restTemplates).isNotNull(); + then(restTemplates.values()).hasSize(1); + RestTemplate restTemplate = restTemplates.values().iterator().next(); + then(restTemplate).isNotNull(); - assertLoadBalanced(restTemplate); - }); + assertLoadBalanced(restTemplate); + }); } @Test void restClientBuilderWithLoadBalancerInterceptor() { - applicationContextRunner.withUserConfiguration(OneRestClientBuilder.class).run(context -> { - final Map restClientBuilders = context.getBeansOfType(RestClient.Builder.class); + applicationContextRunner.withUserConfiguration(OneRestClientBuilder.class) + .run(context -> { + final Map restClientBuilders = context.getBeansOfType(RestClient.Builder.class); - assertThat(restClientBuilders).isNotNull(); - assertThat(restClientBuilders).hasSize(1); - RestClient.Builder restClientBuilder = restClientBuilders.values().iterator().next(); - assertThat(restClientBuilder).isNotNull(); - assertLoadBalanced(restClientBuilder); - }); + assertThat(restClientBuilders).isNotNull(); + assertThat(restClientBuilders).hasSize(1); + RestClient.Builder restClientBuilder = restClientBuilders.values() + .iterator().next(); + assertThat(restClientBuilder).isNotNull(); + assertLoadBalanced(restClientBuilder); + }); } @Test void multipleRestTemplates() { - applicationContextRunner.withUserConfiguration(TwoRestTemplatesAndTwoRestClientBuilders.class).run(context -> { - final Map restTemplates = context.getBeansOfType(RestTemplate.class); + applicationContextRunner.withUserConfiguration(TwoRestTemplatesAndTwoRestClientBuilders.class) + .run(context -> { + final Map restTemplates = context.getBeansOfType(RestTemplate.class); - then(restTemplates).isNotNull(); - Collection templates = restTemplates.values(); - then(templates).hasSize(2); + then(restTemplates).isNotNull(); + Collection templates = restTemplates.values(); + then(templates).hasSize(2); - TwoRestTemplatesAndTwoRestClientBuilders.Two two = context - .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); + TwoRestTemplatesAndTwoRestClientBuilders.Two two = context + .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); - then(two.loadBalanced).isNotNull(); - assertLoadBalanced(two.loadBalanced); + then(two.loadBalanced).isNotNull(); + assertLoadBalanced(two.loadBalanced); - then(two.nonLoadBalanced).isNotNull(); - then(two.nonLoadBalanced.getInterceptors()).isEmpty(); - }); + then(two.nonLoadBalanced).isNotNull(); + then(two.nonLoadBalanced.getInterceptors()).isEmpty(); + }); } @Test void multipleRestClientBuilders() { - applicationContextRunner.withUserConfiguration(TwoRestTemplatesAndTwoRestClientBuilders.class).run(context -> { - final Map restClientBuilders = context.getBeansOfType(RestClient.Builder.class); + applicationContextRunner.withUserConfiguration(TwoRestTemplatesAndTwoRestClientBuilders.class) + .run(context -> { + final Map restClientBuilders = context.getBeansOfType(RestClient.Builder.class); - assertThat(restClientBuilders).isNotNull(); - assertThat(restClientBuilders.values()).hasSize(2); + assertThat(restClientBuilders).isNotNull(); + assertThat(restClientBuilders.values()).hasSize(2); - TwoRestTemplatesAndTwoRestClientBuilders.Two two = context - .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); + TwoRestTemplatesAndTwoRestClientBuilders.Two two = context + .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); - assertThat(two.loadBalancedRestClientBuilder).isNotNull(); - assertLoadBalanced(two.loadBalancedRestClientBuilder); + assertThat(two.loadBalancedRestClientBuilder).isNotNull(); + assertLoadBalanced(two.loadBalancedRestClientBuilder); - assertThat(two.nonLoadBalancedRestClientBuilder).isNotNull(); - two.nonLoadBalancedRestClientBuilder - .requestInterceptors(interceptors -> assertThat(interceptors).isEmpty()); - }); + assertThat(two.nonLoadBalancedRestClientBuilder).isNotNull(); + two.nonLoadBalancedRestClientBuilder + .requestInterceptors(interceptors -> assertThat(interceptors).isEmpty()); + }); } @Test void restTemplatesAndRestClientsFromUsersAutoConfiguration() { applicationContextRunner - .withConfiguration(AutoConfigurations.of(TwoRestTemplatesAndTwoRestClientBuilders.class)) - .run(context -> { - final Map restClientBuilders = context - .getBeansOfType(RestClient.Builder.class); - final Map restTemplates = context.getBeansOfType(RestTemplate.class); + .withConfiguration(AutoConfigurations.of(TwoRestTemplatesAndTwoRestClientBuilders.class)) + .run(context -> { + final Map restClientBuilders = context + .getBeansOfType(RestClient.Builder.class); + final Map restTemplates = context.getBeansOfType(RestTemplate.class); - assertThat(restClientBuilders).isNotNull(); - assertThat(restClientBuilders.values()).hasSize(2); + assertThat(restClientBuilders).isNotNull(); + assertThat(restClientBuilders.values()).hasSize(2); - TwoRestTemplatesAndTwoRestClientBuilders.Two two = context - .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); + TwoRestTemplatesAndTwoRestClientBuilders.Two two = context + .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); - assertThat(two.loadBalancedRestClientBuilder).isNotNull(); - assertLoadBalanced(two.loadBalancedRestClientBuilder); + assertThat(two.loadBalancedRestClientBuilder).isNotNull(); + assertLoadBalanced(two.loadBalancedRestClientBuilder); - assertThat(two.nonLoadBalancedRestClientBuilder).isNotNull(); - two.nonLoadBalancedRestClientBuilder - .requestInterceptors(interceptors -> assertThat(interceptors).isEmpty()); + assertThat(two.nonLoadBalancedRestClientBuilder).isNotNull(); + two.nonLoadBalancedRestClientBuilder + .requestInterceptors(interceptors -> assertThat(interceptors).isEmpty()); - assertThat(restTemplates).isNotNull(); - Collection templates = restTemplates.values(); - assertThat(templates).hasSize(2); + assertThat(restTemplates).isNotNull(); + Collection templates = restTemplates.values(); + assertThat(templates).hasSize(2); - TwoRestTemplatesAndTwoRestClientBuilders.Two twoRestTemplate = context - .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); + TwoRestTemplatesAndTwoRestClientBuilders.Two twoRestTemplate = context + .getBean(TwoRestTemplatesAndTwoRestClientBuilders.Two.class); - assertThat(twoRestTemplate.loadBalanced).isNotNull(); - assertLoadBalanced(twoRestTemplate.loadBalanced); + assertThat(twoRestTemplate.loadBalanced).isNotNull(); + assertLoadBalanced(twoRestTemplate.loadBalanced); - assertThat(twoRestTemplate.nonLoadBalanced).isNotNull(); - assertThat(twoRestTemplate.nonLoadBalanced.getInterceptors()).isEmpty(); - }); + assertThat(twoRestTemplate.nonLoadBalanced).isNotNull(); + assertThat(twoRestTemplate.nonLoadBalanced.getInterceptors()).isEmpty(); + }); + } + + @Test + void loadBalancerRestClientHttpServiceGroupConfigurerPresent() { + applicationContextRunner + .withUserConfiguration(OneRestClientBuilder.class) + .run(context -> { + assertThat(context.getBeansOfType(LoadBalancerRestClientHttpServiceGroupConfigurer.class)) + .hasSize(1); + assertThat(context.getBeansOfType(LoadBalancerWebClientHttpServiceGroupConfigurer.class)) + .hasSize(0); + }); } protected abstract void assertLoadBalanced(RestClient.Builder restClientBuilder); @@ -180,6 +199,11 @@ public abstract class AbstractLoadBalancerAutoConfigurationTests { return RestClient.builder(); } + @Bean + HttpClientServiceProperties httpClientServiceProperties() { + return new HttpClientServiceProperties(); + } + } @Configuration(proxyBeanMethods = false) @@ -198,7 +222,7 @@ public abstract class AbstractLoadBalancerAutoConfigurationTests { } @Configuration(proxyBeanMethods = false) - @Import({ OneRestTemplate.class, OneRestClientBuilder.class }) + @Import({OneRestTemplate.class, OneRestClientBuilder.class}) protected static class TwoRestTemplatesAndTwoRestClientBuilders { @Primary diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriToolsTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriToolsTests.java index 9a70c6c1..8b39274c 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriToolsTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/LoadBalancerUriToolsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 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. @@ -19,13 +19,19 @@ package org.springframework.cloud.client.loadbalancer; import java.net.URI; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.springframework.cloud.client.ServiceInstance; +import org.springframework.web.util.InvalidUrlException; import org.springframework.web.util.UriComponentsBuilder; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; /** * Tests for {@link LoadBalancerUriTools}. @@ -37,7 +43,8 @@ class LoadBalancerUriToolsTests { @Test void originalURIReturnedIfDataMatches() { TestServiceInstance serviceInstance = new TestServiceInstance(); - URI original = UriComponentsBuilder.fromUriString("http://test.example:8080/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("http://test.example:8080/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -47,7 +54,8 @@ class LoadBalancerUriToolsTests { @Test void serviceInstanceHostSet() { TestServiceInstance serviceInstance = new TestServiceInstance(); - URI original = UriComponentsBuilder.fromUriString("http://testHost.example:8080/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("http://testHost.example:8080/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -58,7 +66,8 @@ class LoadBalancerUriToolsTests { @Test void serviceInstanceSchemeSet() { TestServiceInstance serviceInstance = new TestServiceInstance().withScheme("https"); - URI original = UriComponentsBuilder.fromUriString("http://test.example/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("http://test.example/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -69,7 +78,8 @@ class LoadBalancerUriToolsTests { @Test void originalSchemeSetIfServiceInstanceSchemeMissing() { TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null); - URI original = UriComponentsBuilder.fromUriString("https://test.example/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("https://test.example/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -79,8 +89,10 @@ class LoadBalancerUriToolsTests { @Test void secureSchemeSetIfServiceInstanceSchemeMissingAndServiceInstanceSecure() { - TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null).withSecure(true); - URI original = UriComponentsBuilder.fromUriString("http://test.example/xxx").build().toUri(); + TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null) + .withSecure(true); + URI original = UriComponentsBuilder.fromUriString("http://test.example/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -90,8 +102,10 @@ class LoadBalancerUriToolsTests { @Test void secureWsSchemeSetIfServiceInstanceSchemeMissingAndServiceInstanceSecure() { - TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null).withSecure(true); - URI original = UriComponentsBuilder.fromUriString("ws://test.example/xxx").build().toUri(); + TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null) + .withSecure(true); + URI original = UriComponentsBuilder.fromUriString("ws://test.example/xxx").build() + .toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -102,7 +116,8 @@ class LoadBalancerUriToolsTests { @Test void defaultSchemeSetIfMissing() { TestServiceInstance serviceInstance = new TestServiceInstance().withScheme(null); - URI original = UriComponentsBuilder.fromUriString("//test.example/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("//test.example/xxx").build() + .toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -113,7 +128,8 @@ class LoadBalancerUriToolsTests { @Test void serviceInstancePortSet() { TestServiceInstance serviceInstance = new TestServiceInstance().withPort(0); - URI original = UriComponentsBuilder.fromUriString("http://test.example:8080/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("http://test.example:8080/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -124,7 +140,8 @@ class LoadBalancerUriToolsTests { @Test void defaultHttpPortSetIfServiceInstancePortIncorrect() { TestServiceInstance serviceInstance = new TestServiceInstance().withPort(-1); - URI original = UriComponentsBuilder.fromUriString("http://test.example:8888/xxx").build().toUri(); + URI original = UriComponentsBuilder.fromUriString("http://test.example:8888/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -134,8 +151,10 @@ class LoadBalancerUriToolsTests { @Test void defaultHttpsPortSetIfServiceInstancePortIncorrect() { - TestServiceInstance serviceInstance = new TestServiceInstance().withScheme("https").withPort(-1); - URI original = UriComponentsBuilder.fromUriString("http://test.example:8888/xxx").build().toUri(); + TestServiceInstance serviceInstance = new TestServiceInstance().withScheme("https") + .withPort(-1); + URI original = UriComponentsBuilder.fromUriString("http://test.example:8888/xxx") + .build().toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -147,9 +166,9 @@ class LoadBalancerUriToolsTests { void originalUserInfoSet() { TestServiceInstance serviceInstance = new TestServiceInstance(); URI original = UriComponentsBuilder - .fromUriString("http://testUser@testHost.example/path?query1=test1&query2=test2#fragment") - .build() - .toUri(); + .fromUriString("http://testUser@testHost.example/path?query1=test1&query2=test2#fragment") + .build() + .toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -167,9 +186,9 @@ class LoadBalancerUriToolsTests { void reconstructedURIEncodedCorrectly() { TestServiceInstance serviceInstance = new TestServiceInstance(); URI original = UriComponentsBuilder - .fromUriString("http://test.example/path%40%21%242?query=val%40%21%242#frag%40%21%242") - .build() - .toUri(); + .fromUriString("http://test.example/path%40%21%242?query=val%40%21%242#frag%40%21%242") + .build() + .toUri(); URI reconstructed = LoadBalancerUriTools.reconstructURI(serviceInstance, original); @@ -183,6 +202,34 @@ class LoadBalancerUriToolsTests { assertThat(reconstructed.getPort()).isEqualTo(serviceInstance.getPort()); } + @ParameterizedTest(name = "{index} => url={0}, serviceId={1}, expected={2}") + @MethodSource("provideUrlAndServiceIdForIsServiceIdUrl") + void verifyServiceIdUrl(String url, String serviceId, boolean expected) { + assertThat(LoadBalancerUriTools.isServiceIdUrl(url, serviceId)) + .isEqualTo(expected); + } + + @Test + void verifyServiceIdIncorrectUrl() { + assertThatExceptionOfType(InvalidUrlException.class) + .isThrownBy(() -> { + URI baseUrl = UriComponentsBuilder.fromUriString("https://:testService/xxx") + .build().toUri(); + + LoadBalancerUriTools.isServiceIdUrl(String.valueOf(baseUrl), null); + }); + + } + + private static Stream provideUrlAndServiceIdForIsServiceIdUrl() { + return Stream.of( + org.junit.jupiter.params.provider.Arguments.of("https://testService/xxx", "testService", true), + org.junit.jupiter.params.provider.Arguments.of("https://test/xxx", "testService", false), + org.junit.jupiter.params.provider.Arguments.of("https://testService/xxx", null, false), + org.junit.jupiter.params.provider.Arguments.of(null, "testService", false) + ); + } + } class TestServiceInstance implements ServiceInstance { diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java index 0d0f3c6c..4b550db3 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2025 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. @@ -23,19 +23,24 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.http.client.reactive.service.ReactiveHttpClientServiceProperties; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; import org.springframework.cloud.client.loadbalancer.LoadBalancerClientsProperties; import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.client.loadbalancer.LoadBalancerRestClientHttpServiceGroupConfigurer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.web.reactive.function.client.WebClient; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.BDDAssertions.then; import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.assertLoadBalanced; import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.getFilters; @@ -59,9 +64,10 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { assertLoadBalanced(webClientBuilder, ReactorLoadBalancerExchangeFilterFunction.class); final Map testServiceMap = context - .getBeansOfType(OneWebClientBuilder.TestService.class); + .getBeansOfType(OneWebClientBuilder.TestService.class); then(testServiceMap).isNotNull().hasSize(1); - OneWebClientBuilder.TestService testService = testServiceMap.values().stream().findFirst().get(); + OneWebClientBuilder.TestService testService = testServiceMap.values().stream() + .findFirst().get(); assertLoadBalanced(testService.webClient, ReactorLoadBalancerExchangeFilterFunction.class); } @@ -78,9 +84,10 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { assertLoadBalanced(webClientBuilder, RetryableLoadBalancerExchangeFilterFunction.class); final Map testServiceMap = context - .getBeansOfType(OneWebClientBuilder.TestService.class); + .getBeansOfType(OneWebClientBuilder.TestService.class); then(testServiceMap).isNotNull().hasSize(1); - OneWebClientBuilder.TestService testService = testServiceMap.values().stream().findFirst().get(); + OneWebClientBuilder.TestService testService = testServiceMap.values().stream() + .findFirst().get(); assertLoadBalanced(testService.webClient, RetryableLoadBalancerExchangeFilterFunction.class); System.clearProperty("spring.cloud.loadbalancer.retry.enabled"); @@ -136,18 +143,34 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { @Test void defaultPropertiesWorks() { ConfigurableApplicationContext context = new SpringApplicationBuilder().web(WebApplicationType.NONE) - .sources(OneWebClientBuilder.class, DefaulConfig.class) - .properties("spring.cloud.loadbalancer.health-check.initial-delay=1s", - "spring.cloud.loadbalancer.clients.myclient.health-check.interval=30s") - .run(); + .sources(OneWebClientBuilder.class, DefaulConfig.class) + .properties("spring.cloud.loadbalancer.health-check.initial-delay=1s", + "spring.cloud.loadbalancer.clients.myclient.health-check.interval=30s") + .run(); LoadBalancerClientsProperties properties = context.getBean(LoadBalancerClientsProperties.class); then(properties.getClients()).containsKey("myclient"); LoadBalancerProperties clientProperties = properties.getClients().get("myclient"); // default value - then(clientProperties.getHealthCheck().getInitialDelay()).isEqualTo(Duration.ofSeconds(1)); + then(clientProperties.getHealthCheck() + .getInitialDelay()).isEqualTo(Duration.ofSeconds(1)); // client specific value - then(clientProperties.getHealthCheck().getInterval()).isEqualTo(Duration.ofSeconds(30)); + then(clientProperties.getHealthCheck() + .getInterval()).isEqualTo(Duration.ofSeconds(30)); + } + + @Test + void loadBalancerRestClientHttpServiceGroupConfigurerPresent() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(ReactorLoadBalancerClientAutoConfiguration.class, + LoadBalancerBeanPostProcessorAutoConfiguration.class)) + .withUserConfiguration(OneWebClientBuilder.class) + .run(context -> { + assertThat(context.getBeansOfType(LoadBalancerWebClientHttpServiceGroupConfigurer.class)) + .hasSize(1); + assertThat(context.getBeansOfType(LoadBalancerRestClientHttpServiceGroupConfigurer.class)) + .hasSize(0); + }); } private ConfigurableApplicationContext init(Class config) { @@ -221,6 +244,11 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { } + @Bean + ReactiveHttpClientServiceProperties reactiveHttpClientServiceProperties() { + return new ReactiveHttpClientServiceProperties(); + } + } @Configuration