0
import com.ssctech.eventmsg.app.model.EstimatedCash; 
import com.ssctech.eventmsg.app.properties.KongAPIProperties;
import lombok.extern.slf4j.Slf4j; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.stereotype.Service; 
import org.springframework.web.reactive.function.client.WebClient; 

import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;

public class KongAPIService {

    public static final String KONG_REGISTRATION_ID = "kong";

    @Autowired
    @Qualifier("kongApi")
    private WebClient webClient;

    @Autowired
    private KongAPIProperties kongAPIProperties;

    public EstimatedCash getEstimatedCash(String fundSponsorId, String positionId, String transId1, String transId2, String system) {

        try {
            return webClient.get()
                .uri(kongAPIProperties.getCashAvailabilityUri(), positionId, transId1, transId2)
                .attributes(clientRegistrationId(KONG_REGISTRATION_ID))
                .header("authorizationContext", "operator=" + kongAPIProperties.getAuthorizationContext())
                .header("fundSponsorId", fundSponsorId)
                .header("securityChannel", kongAPIProperties.getSecurityChannel())
                .header("system", system)
                .header("tenant", kongAPIProperties.getTenant())
                .retrieve()
                .bodyToMono(EstimatedCash.class)
                .block();
        } catch(Exception e) {
            log.error("Cannot get Cash Availability Info from API for " + "transId1 = " + transId1 + " / " + "transId2 = " + transId2, e);
            return new EstimatedCash();
        }
    }

}

clientRegistrationId(KONG_REGISTRATION_ID) this is static method i am not able to write junit test for this method how to mock it without using PowerMock by using mockito only.

package com.ssctech.eventmsg.app.service;

import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.when;
import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.web.reactive.function.client.WebClient;
import org.mockito.Matchers;

import com.ssctech.eventmsg.app.model.EstimatedCash;
import com.ssctech.eventmsg.app.properties.KongAPIProperties;

import reactor.core.publisher.Mono;

@RunWith(MockitoJUnitRunner.class)
public class KongAPIServiceTest {
    @InjectMocks
    KongAPIService KongApiService;
    @Mock
    WebClient webClient;
    @Mock
    WebClient.RequestBodyUriSpec requestBodyUriSpec;
    @Mock
    WebClient.RequestHeadersUriSpec requestHeadersUriSpec;
    @Mock
    WebClient.RequestHeadersSpec requestHeadersSpec;
    @Mock
    WebClient.RequestBodySpec requestBodySpec;
    @Mock
    WebClient.ResponseSpec responseSpec;
    @Mock
    EstimatedCash estimate;
    @Mock
    Mono mono;
    @Mock
    Consumer<Map<String, Object>> consumer;
    private KongAPIProperties kongAPIProperties=new KongAPIProperties();
    Map<String, Object> mp = new HashMap<>();

    @Before
    public void setup() {
        KongApiService = new KongAPIService();
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void postTest() throws Exception {
        when(webClient.get()).thenReturn(requestHeadersUriSpec);
        kongAPIProperties.setCashAvailabilityUri("available");
        when(requestHeadersUriSpec.uri(Matchers.any(String.class), Matchers.any(String.class), Matchers.any(String.class),
                Matchers.any(String.class))).thenReturn(requestHeadersUriSpec);
//      when(requestHeadersSpec.attributes(consumer)).thenReturn(requestBodySpec);
//      when(requestHeadersSpec.header(Matchers.any(String.class), Matchers.any(String.class)))
//              .thenReturn(requestHeadersSpec);
//      when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
//      when(responseSpec.bodyToMono(Matchers.any(Class.class))).thenReturn(mono);
//      when(mono.block()).thenReturn(new String());
        assertNotNull(KongApiService.getEstimatedCash("001", "1", "id1", "id2", "mfa"));
    }

}
rieckpil
  • 10,470
  • 3
  • 32
  • 56
ravi
  • 1
  • 2
  • this might help: https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito – Stultuske Apr 20 '21 at 07:23
  • As part of which class is the static method `clientRegistrationId(KONG_REGISTRATION_ID)`? Can you please add the import section for your test class and maybe elaborate with 1-2 sentences your intend of the test – rieckpil Apr 20 '21 at 10:35

3 Answers3

0

It is impossible to mock static methods using mockito only.

talex
  • 17,973
  • 3
  • 29
  • 66
  • Why is this impossible? Starting with [version 3.4.0](https://rieckpil.de/mocking-static-methods-with-mockito-java-kotlin/), Mockito supports mocking static methods – rieckpil Apr 20 '21 at 10:32
  • Didn't know that. You may consider to add it as answer. – talex Apr 20 '21 at 11:36
0

There's little value in mocking the entire WebClient interaction as you end up mocking everything and literally with a copy of your implementation. That's brittle and won't help when refactoring your code.

When testing a class that interacts with an HTTP Client I would recommend spawning a local HTTP server and mock the HTTP response. The MockWebServer works perfectly for this use case or WireMock/MockServer.

Most of these local mock servers allow to retrieve the request afterward so that you can inspect if all headers are present.

For the static method access, you can use Mockito to mock the method (if needed):

try (MockedStatic<ServerOAuth2AuthorizedClientExchangeFilterFunction> mockedStatic = Mockito.mockStatic(ServerOAuth2AuthorizedClientExchangeFilterFunction.class)) {

  mockedStatic
    .when(() -> ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId(eq("KONG_REGISTRATION_ID")))
    .thenReturn("YOUR_ID");

  // ...
}

If you're still planning to write a test and mock everything, consider deep stubs to avoid a lot of boilerplate code inside your test.

rieckpil
  • 10,470
  • 3
  • 32
  • 56
0

I had the same exact problem. I found a work around. Use Mockito.notNull() like this:

when(requestBodyMock.attributes(notNull())).thenReturn(requestBodyMock);

I wasn't able to use the deep stubbing on this, it wouldn't work. Hope this helps others.

Tarun
  • 685
  • 3
  • 16
aahmed31
  • 39
  • 1
  • 7