I want to test this class :
public class TokenIntrospector {
private RestTemplate restTemplate;
private String userInfoUri = "http://localhost";
public TokenIntrospector(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public String introspect(String data) {
var userinfo = findUserInfo(data);
return userinfo.name();
}
private UserInfo findUserInfo(String token) {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.set("Accept", "application/json");
headers.set("Authorization", format("Bearer %s", token));
var userinfoRequest = new HttpEntity<UserInfo>(headers);
var userinfo = restTemplate.exchange(userInfoUri,
HttpMethod.GET,
userinfoRequest,
UserInfo.class);
return userinfo.getBody();
}
}
The issue comes from this line :
restTemplate.exchange(userInfoUri,
HttpMethod.GET,
userinfoRequest,
UserInfo.class);
It is calling this method (in Spring code) :
public <T> ResponseEntity<T> exchange(String url, HttpMethod method,
@Nullable HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables)
throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(requestEntity, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return nonNull(execute(url, method, requestCallback, responseExtractor, uriVariables));
}
Here is my test code :
@ExtendWith(MockitoExtension.class)
public class TokenIntrospectorTest {
@InjectMocks
private TokenIntrospector tokenIntrospector;
@Mock
RestTemplate restTemplate;
@Test
public void test() {
when(restTemplate.exchange(
anyString(),
any(HttpMethod.class),
any(HttpEntity.class),
any(Class.class),
Optional.ofNullable(any()))
).thenReturn(ResponseEntity.ok(new UserInfo(
"a")));
String introspect = tokenIntrospector.introspect("data");
}
}
Here is the error I got :
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'exchange' method:
restTemplate.exchange(
"http://localhost",
GET,
<[Accept:"application/json", Authorization:"Bearer data"]>,
class com.example.UserInfo
);
-> at com.example.TokenIntrospector.findUserInfo(TokenIntrospector.java:35)
- has following stubbing(s) with different arguments:
1. restTemplate.exchange(
"",
null,
null,
null,
Optional.empty
);
-> at com.example.TokenIntrospectorTest.test(TokenIntrospectorTest.java:32)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
5
Optional.ofNullable(any())
does not make sense. If you stub a method call, you can either use direct arguments or only argument matchers. Optinnal.ofNullable(any())
is not a matcher and equivalent to Optional.empty()
(but it will pollute Mockito’s argument matching stack).
So maybe you wanted to say any(Optional.class)
or eq(Optional.empty())
?
That said, your code is only passing 4 arguments to the exchange method, so you must stub the call with 4 arguments and not the call with 5 arguments:
when(
restTemplate.exchange(
eq("http://localhost),
eq(HttpMethod.GET),
any(HttpEntity.class),
eq(UserInfo.class))
.thenReturn(…);