How to mock Spring WebClient and builder

Viewed 4232

I am trying to mock Spring WebClient and am having issues with the WebClient.builder() mocking. The mocks I've defined so far in my test are not being used, I think because this builder does not return my mock WebClient. How can I get the builder to return my mock?

WebClient webClient = WebClient.builder()
                .exchangeStrategies(ExchangeStrategies.builder()
                .codecs(configurer -> configurer
                        .defaultCodecs()
                        .maxInMemorySize(16 * 1024 * 1024))
                .build())
                .clientConnector(new ReactorClientHttpConnector(HttpClient.newConnection().compress(true)))
                .build();

and the WebClient is used as so:

response = webClient
            .get()
            .uri(URLDecoder.decode(someEndpoint.replace("\"", ""), CLIENT_ENCODING))
            .header(AUTHORIZATION, BEARER + accessToken)
            .accept(MediaType.APPLICATION_JSON)
            .retrieve().bodyToMono(JsonNode.class).block();

I do not see any problems with the mocks as I followed these solutions: How to mock Spring WebFlux WebClient? but the mocks are not being used. How can I mock the builder/return my mock from the builder?

1 Answers

You need to mock the static method builder() of WebClient. Indeed, if this method is not mocked, mockito can't edit the behaviour of this method. Therefore, your mocked webClient is not used. To perfom that, you need to include this dependency in your pom.xml if you use maven.

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.4.6</version>
    <scope>test</scope>
</dependency>

This will provide mockStatic() method on Mockito and can be used like :

MockedStatic<WebClient> webClientStatic = Mockito.mockStatic(WebClient.class);
webClientStatic.when(WebClient::builder).thenReturn(webClientBuilder);

webClientBuilder must be mocked because we need to change behaviour of its method build() to return your mocked webClient.

Mockito.when(webClientBuilder.build()).thenReturn(mockedWebClient);

To resume all in one code :

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import org.mockito.MockedStatic;

@RunWith(MockitoJUnitRunner.class)
public class WebClientTest {

    @Mock
    private WebClient.Builder webClientBuilder;

    @Mock
    private WebClient mockedWebClient;

    @Before
    public void setup() {
        Mockito.when(webClientBuilder.exchangeStrategies(Mockito.any(ExchangeStrategies.class))).thenReturn(webClientBuilder);
        Mockito.when(webClientBuilder.clientConnector(Mockito.any(ReactorClientHttpConnector.class))).thenReturn(webClientBuilder);
        Mockito.when(webClientBuilder.build()).thenReturn(mockedWebClient);
    }

    @Test
    public void testWebClient() {
        final MockedStatic<WebClient> webClientStatic = Mockito.mockStatic(WebClient.class);
        webClientStatic.when(WebClient::builder).thenReturn(webClientBuilder);

        final WebClient webClient = WebClient.builder()
                .exchangeStrategies(ExchangeStrategies.builder()
                        .codecs(configurer -> configurer
                                .defaultCodecs()
                                .maxInMemorySize(16 * 1024 * 1024))
                        .build())
                .clientConnector(new ReactorClientHttpConnector(HttpClient.newConnection().compress(true)))
                .build();

        //It throws error if webClient is not mockedWebClient
        Assert.assertEquals(webClient, mockedWebClient);
    }
}

You can test it.

Related