I'm having problems mocking the response object of my Test Class when using Mockito. I'm trying to test an exception, for this I need one of the attributes of the Class that returns from the POST request. I've successfully mocked the RestTemplate but my when().thenReturn() is not returning anything and I'm getting a null pointer exception at the "if" validation. If anyone could help me on this problem I would be very grateful.
Here is my Service Class:
@Service
public class CaptchaValidatorServiceImpl implements CaptchaValidatorService{
private static final String GOOGLE_CAPTCHA_ENDPOINT = "someEndpoint";
private String stage;
private String captchaSecret;
private RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
@Override
public void checkToken(String token) throws Exception{
MultiValueMap<String,String> requestMap = new LinkedValueMap<>();
requestMap.add("secret", captchaSecret);
requestMap.add("response", token);
try{
CaptchaResponse response = restTemplate.postForObject(GOOGLE_CAPTCHA_ENDPOINT,
requestMap, CaptchaResponse.class);
if(!response.getSuccess()){
throw new InvalidCaptchaTokenException("Invalid Token");
}
} catch (ResourceAccessException e){
throw new CaptchaValidationNotPossible("No Response from Server");
}
}
private SimpleClientHttpRequestFactory getClientHttpRequestFactory(){
...
}
}
And here is my Test Class:
@SpringBootTest
public class CaptchaValidatorTest{
@Mock
private RestTemplate restTemplate;
@InjectMocks
@Spy
private CaptchaValidatorServiceImpl captchaValidatorService;
private CaptchaResponse captchaResponse = mock(CaptchaResponse.class);
@Test
public void shouldThrowInvalidTokenException() {
captchaResponse.setSuccess(false);
Mockito.when(restTemplate.postForObject(Mockito.anyString(),
ArgumentMatchers.any(Class.class), ArgumentMatchers.any(Class.class)))
.thenReturn(captchaResponse);
Exception exception = assertThrows(InvalidCaptchaTokenException.class, () ->
captchaValidatorService.checkToken("test"));
assertEquals("Invalid Token", exception.getMessage());
}
}
CodePudding user response:
In my opinion it could be a problem with ArgumentMatchers. Method postForObject require parameters as String, MultiValueMap(or parent) and Class, but you set in Mockito.when: anyString() (correct), any(Class.class) (but MultiValueMap is passed - probably incorrect) and any(Class.class) (correct).
Try use:
Mockito.when(restTemplate.postForObject(ArgumentMatchers.any(String.class),
ArgumentMatchers.any(MultiValueMap.class), ArgumentMatchers.any(Class.class)))
.thenReturn(captchaResponse);
EDIT: It seems to me that the CaptchaResponse in the test is unnecessarily a mock:
private CaptchaResponse captchaResponse = mock(CaptchaResponse.class);
but if You want this in that way, I think u need to replace:
captchaResponse.setSuccess(false);
to something like:
Mockito.when(captchaResponse.getSuccess()).thenReturn(false);