I have a variable which is generic i.e
ParameterizedTypeReference<?> parameterizedTypeReference = new ParameterizedTypeReference<List<Object>>() {}
The actual method looks like:
public <T, U> U post(String serviceUrl, T data, ParameterizedTypeReference<U> ref, String bearerToken) {
ParameterizedTypeReference<?> parameterizedTypeReference = new ParameterizedTypeReference<List<Object>>() {
}:
var responseBodyMono = webClient
.post()
.uri(serviceUrl)
.header(HttpHeaders.AUTHORIZATION, bearerToken)
.header(X_CORRELATION_ID, MDC.get(X_CORRELATION_ID))
.body(Mono.just(data), parameterizedTypeReference) // I want to mock this
}
I have written test case like
@Mock
WebClient.RequestHeadersSpec requestHeadersSpec;
@Mock
WebClient.RequestHeadersUriSpec requestHeadersUriSpec;
@Mock
WebClient.RequestBodyUriSpec requestBodyUriSpec;
@Test
public void testPost() {
ParameterizedTypeReference<?> parameterizedTypeReference1 = new ParameterizedTypeReference<List<Object>>() {};
Mockito.when(webClient.post()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(SERVICE_URL)).thenReturn(requestBodySpec);
when(requestBodySpec.header(eq(HttpHeaders.AUTHORIZATION), eq(BEARER_TOKEN))).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.header(anyString(), Mockito.isNull())).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.body(Mono.just(anyString()), eq(parameterizedTypeReference1))).thenReturn(requestHeadersSpec); // Here I have tried to mock
assertNotNull(webClientService.post(SERVICE_URL, Collections.emptyList(), parameterizedTypeReference, BEARER_TOKEN));
}
But I get error saying
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'body' method:
requestBodyUriSpec.body(
MonoJust,
ParameterizedTypeReference<T>
);
-> at com.radisys.macs.cems.common.webclient.WebClientService.getResponseEntity(WebClientService.java:310)
- has following stubbing(s) with different arguments:
1. requestBodyUriSpec.body(MonoJust, null);
-> at com.radisys.macs.cems.common.webclient.WebClientServiceTest.testGetResponseEntity(WebClientServiceTest.java:224)
How can the parametrizedTypeReference
be null? When I have nicely mocked it?
EDIT After trying the answer, the following was the error
java: no suitable method found for thenReturn(reactor.core.publisher.Mono<java.util.List<java.lang.String>>)
method org.mockito.stubbing.OngoingStubbing.thenReturn(reactor.core.publisher.Mono<capture#1 of ?>) is not applicable
(argument mismatch; inference variable T has incompatible bounds
equality constraints: capture#1 of ?
lower bounds: java.util.List<T>)
method org.mockito.stubbing.OngoingStubbing.thenReturn(reactor.core.publisher.Mono<capture#1 of ?>,reactor.core.publisher.Mono<capture#1 of ?>...) is not applicable
(argument mismatch; inference variable T has incompatible bounds
equality constraints: capture#1 of ?
lower bounds: java.util.List<T>)
EDIT 2
Changed to
ParameterizedTypeReference parameterizedTypeReference1 = new ParameterizedTypeReference<List<Object>>() {}; // removed <?>
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'body' method:
requestBodyUriSpec.body(
MonoJust,
ParameterizedTypeReference<java.util.List<java.lang.Object>>
);
-> at com.radisys.macs.cems.common.webclient.WebClientService.post(WebClientService.java:185)
- has following stubbing(s) with different arguments:
1. requestBodyUriSpec.body(null, null);
-> at com.radisys.macs.cems.common.webclient.WebClientServiceTest.testPost(WebClientServiceTest.java:131)
Extra info please ignore this, for the SO
If this helps EXTRA INFO:
For the below code
public <T, U> U update(String serviceUrl, T payload, ParameterizedTypeReference<U> ref, String bearerToken) {
LOGGER.atFine().log(SERVICE_URL_LOGGER, serviceUrl);
ParameterizedTypeReference<T> parameterizedTypeReference = new ParameterizedTypeReference<>() {
};
Mono<U> responseStatusMono = webClient
.put()
.uri(serviceUrl)
.header(HttpHeaders.AUTHORIZATION, bearerToken)
.header(X_CORRELATION_ID, MDC.get(X_CORRELATION_ID))
.body(Mono.just(payload), parameterizedTypeReference)
.retrieve()
.onStatus(HttpStatusCode::isError, response -> com.radisys.macs.cems.common.webclient.SBServiceErrorHandlerUtil.logAndGetThrowableMono(serviceUrl,
response))
.bodyToMono(ref)
.doOnError(com.radisys.macs.cems.common.webclient.SBServiceErrorHandlerUtil::handleConnectionErrors);
var responseStatus = responseStatusMono.block();
LOGGER.atFine().log("update operation response from SB Service: %s", responseStatus);
return responseStatus;
}
Test case is
@Test
public void testUpdate() {
when(webClient.put()).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.uri(WebClientServiceTest.SERVICE_URL)).thenReturn(requestBodySpec);
when(requestBodySpec.header(eq(HttpHeaders.AUTHORIZATION), eq(WebClientServiceTest.BEARER_TOKEN))).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.header(anyString(), Mockito.isNull())).thenReturn(requestBodyUriSpec);
when(requestBodyUriSpec.body(any(), any(ParameterizedTypeReference.class))).thenReturn(requestHeadersSpec);
when(requestHeadersSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.onStatus(any(), any())).thenReturn(responseSpec);
when(responseSpec.bodyToMono(eq(parameterizedTypeReference))).thenReturn(Mono.just(Collections.singletonList("record1")));
assertNotNull(webClientService.update(WebClientServiceTest.SERVICE_URL, Collections.emptyList(), parameterizedTypeReference, WebClientServiceTest.BEARER_TOKEN));
}
The below is working just fine, but for the post it is not working, I am amazed how it is working for update, and not for post request :(
You cannot mix matcher arguments with non-matcher arguments.
Mixes a non-matcher argument (
Mono.just
) with a matcher argument (ArgumentMatchers.eq
). The implementation of the matcher methods returnsnull
(or the default value for the type, e.g.false
for booleans and0
for numeric types).Mockito should usually catch this and would normally print an error message informing about the mixed usage. The problem is that you record a second matcher as argument to
Mono.just
, preventing Mockito from detecting this mistake.You need to use matchers for all arguments or no matchers at all. Here's a correct version using matchers for all arguments: