如何测试响应式 Oauth2 WebClient?

问题描述 投票:0回答:1

我是 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”,它正在生成错误。但是“正常”运行应用程序会使用不同的管理器,这不会导致相同的错误。

对于编写我应该简单的测试有什么帮助吗?

java webclient reactive
1个回答
0
投票

我确实找到了预期类似的非反应性相关但与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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.