GebanaPaet
GebanaPaet

Reputation: 1

How to Test an Reactive Oauth2 WebClient?

i am new to reactive Programming with Java and somehow i am missing a point in writing a test for my Reactive WebClient.

I am using The following reactive WebClientConfig

@Configuration
public class DynamicsWebClientConfig {

    @Bean
    WebClient dynamicsClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
                new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth2Client.setDefaultClientRegistrationId("dynamics");
        return WebClient.builder()
                .filter(oauth2Client)
                .build();

    }
}

Using that Client within an Controller within an "normal application run" will always work correctly doing the Oauth2 when neccecary and then reqeusting the Data, so i thought lets write a test for that so i am sure this always works. Thats why i ended up with the following 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);
    }

}

Running the TEST will result in the Error serverWebExchange cannot be null at org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$authorize$4

I thought when using @SpringBootTest the full apllication Context is loaded and i can do test as i would use the application. Yet this Error suggests that my reactive Application Test is not loaded Properly. Am i missing something is reactiveApplications handled differently?

I found out that i could use WebFluxTest but this would not load the application context properly therefor the configuration classes will not be loaded and i am still not able to do an oauth2 reactive webclient request.

I also tried:

Somehow my Test seams to be using "DefaultReactiveOAuth2AuthorizedClientManager" which is generating the Error. But running the Application "normaly" there seams to be used a different Manager which will not result in the same Error.

Any help with writing my supposed to be Easy Test?

Upvotes: -1

Views: 75

Answers (1)

GebanaPaet
GebanaPaet

Reputation: 1

I did find the solution anticipating a similar not reactive related but oauth related Solution here `servletRequest cannot be null` -> SpringBoot - WebClient - GET request with Keycloak

To the WebClient config needs to be added an AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager as follows

@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;
}
}

`

You are able to test the ReactiveEndPoint as follows:

@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);
    }
}

Upvotes: 0

Related Questions