我是 Java 反应式编程新手,不知何故,我在为我的反应式 WebClient 编写测试时遗漏了一点。
我正在使用以下反应式 WebClientConfig
@Configuration
public class DynamicsWebClientConfig {
@Bean
WebClient dynamicsClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2Client.setDefaultClientRegistrationId("dynamics");
return WebClient.builder()
.filter(oauth2Client)
.build();
}
}
在“正常应用程序运行”中的控制器中使用该客户端将始终可以正确工作,在需要时执行 Oauth2,然后请求数据,所以我想让我们为此编写一个测试,所以我确信这总是有效。这就是为什么我最终得到以下 TestClass
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
public class DynamicsClientTest {
@Autowired
private WebClient dynamicsClient;
@Test
public void testDynamicsClient() {
String responseBody = dynamicsClient.get()
.uri("https://api.businesscentral.dynamics.com/<some_ids_an_context_here>/customers")
.retrieve()
.bodyToMono(String.class)
.block();
assertNotNull(responseBody);
assertEquals("expectedData", responseBody);
}
}
运行测试将导致错误 serverWebExchange 不能为空,位于 org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$authorize$4
我认为使用 @SpringBootTest 时会加载完整的应用程序上下文,我可以像使用该应用程序一样进行测试。然而,此错误表明我的反应式应用程序测试未正确加载。我是否遗漏了一些反应性应用程序处理方式不同的东西?
我发现我可以使用 WebFluxTest,但这不会正确加载应用程序上下文,因此配置类不会被加载,而且我仍然无法执行 oauth2 反应式 webclient 请求。
我也尝试过:
不知何故,我的测试接缝正在使用“DefaultReactiveOAuth2AuthorizedClientManager”,它正在生成错误。但是“正常”运行应用程序会使用不同的管理器,这不会导致相同的错误。
对于编写我应该简单的测试有什么帮助吗?
我确实找到了预期类似的非反应性相关但与oauth相关的解决方案在这里`servletRequest不能为空` - > SpringBoot - WebClient - 使用Keycloak的GET请求
需要在 WebClient 配置中添加 AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager 如下
@Configuration
public class DynamicsWebClientConfig {
@Bean
WebClient dynamicsClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2Client.setDefaultClientRegistrationId("dynamics");
return WebClient.builder()
.filter(oauth2Client)
.build();
}
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService clientService) {
// Configure the authorized client provider with refresh token and client credentials
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken()
.clientCredentials()
.build();
// Instantiate the AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, clientService);
// Set the authorized client provider
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
`
您可以按如下方式测试 ReactiveEndPoint:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT )
public class DynamicsClientTest {
@Autowired
private WebClient dynamicsClient;
@Test
public void testDynamicsClient() {
// Use the dynamicsClient to make a request
String responseBody = dynamicsClient.get()
.uri(<some_api_endpint_here>/customers)
.retrieve()
.bodyToMono(String.class)
.block();
// Validate that the response is not null and matches the expected result
assertNotNull(responseBody);
// You might want to validate the response further, depending on your requirements
// For example: assertEquals("expectedData", responseBody);
}
}