Search code examples
mockitospring-webfluxpowermockito

What is the argument matcher for a Mono type parameter?


Class under test:



import java.time.Duration;
import java.time.Instant;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class ServiceProcessorImpl implements ServiceProcessor {

    @Autowired
    private WebClient webClient;


    @Override
    public Mono<ServiceResponse> fetchOffersByItemIdAndStoreId(Mono<List<PriceAndOfferRequest>> list) {
        String url = "<some url>";
        Mono<ServiceResponse> response = webClient
                        .post()
                        .uri(url)
                        .headers(httpHeaders -> getHeaders(httpHeaders))
                        .body(list,List.class)
                        .retrieve()
                        .onStatus(HttpStatus::isError, clientResponse -> {
                            log.error("Error on API Calling :  {}", clientResponse.statusCode());
                            return Mono.empty();
                        })
                        .bodyToMono(PnOServiceResponse.class);
        return response;
    }
}

Test Case:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@RunWith(SpringRunner.class)
public class ServiceProcessorImplTest {

    @Mock
    private static WebClient webClientMock;
    
    @Mock
    private WebClient.RequestHeadersSpec requestHeadersSpecMock;
    @Mock
    private WebClient.RequestHeadersUriSpec requestHeadersUriSpecMock;
    @Mock
    private WebClient.RequestBodySpec requestBodySpecMock;
    @Mock
    private WebClient.RequestBodyUriSpec requestBodyUriSpecMock;
    @Mock
    private WebClient.ResponseSpec responseSpecMock;

    @InjectMocks
    static ServiceProcessorImpl pnOServiceProcessor;

    @Test
    public void test_whenErrorFromService_thenMonoEmpty() {
        Mockito.when(webClientMock.post()).thenReturn(requestBodyUriSpecMock);
        Mockito.when(requestBodyUriSpecMock.uri(Mockito.anyString())).thenReturn(requestBodySpecMock);
        Mockito.when(requestBodySpecMock.headers(Mockito.any())).thenReturn(requestBodySpecMock);
        Mockito.when(requestBodySpecMock.body(Mockito.any(Mono.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);
        Mockito.when(requestHeadersSpecMock.retrieve()).thenReturn(responseSpecMock);
        Mockito.when(responseSpecMock.onStatus(Mockito.any(), Mockito.any())).thenReturn(responseSpecMock);
        Mockito.when(responseSpecMock.bodyToMono(Mockito.eq(PnOServiceResponse.class))).thenReturn(Mono.empty());

        Mono<List<PriceAndOfferRequest>> reqList = createPriceAndOfferRequestList();
        Mono<PnOServiceResponse> pnOServiceResponseMono = pnOServiceProcessor.fetchOffersByItemIdAndStoreId(reqList);

        StepVerifier.create(pnOServiceResponseMono)
                .expectNextCount(0)
                .verifyComplete();
    }

    private Mono<List<PriceAndOfferRequest>> createPriceAndOfferRequestList() {
        PriceAndOfferRequest pnoRequest = new PriceAndOfferRequest();
        pnoRequest.setItemId("12345");
        pnoRequest.setStoreNumber("store12345");
        List<PriceAndOfferRequest> list = Arrays.asList(pnoRequest);
        return Mono.just(list);
    }

    private Mono<PnOServiceResponse> createMockPnOResponse() {
        PnOServiceResponse pnOServiceResponse = new PnOServiceResponse();
        OfferPriceDTO offerPriceDTO = new OfferPriceDTO();
        PnOItem item = new PnOItem();
        item.setItemId("12345");
        offerPriceDTO.setItems(Arrays.asList(item));
        pnOServiceResponse.setOfferPriceDTO(offerPriceDTO);
        return Mono.just(pnOServiceResponse);
    }
}

The code gives NullPointerException while calling .body() on the webClient in fetchOffersByItemIdAndStoreId method. Looks like there is some issue with the ArgumentMatcher in the test case when mocking the call to body() in Mockito.when(requestBodySpecMock.body(Mockito.any(Mono.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);


Solution

  • Resolved.

    Mockito.any(Object.class) worked me.

    Mockito.when(requestBodySpecMock.body(Mockito.any(Object.class), Mockito.any(Class.class))).thenReturn(requestHeadersSpecMock);