Home > database >  Spring Boot / Mockito: Mocking RestTemplate but Response Always Null
Spring Boot / Mockito: Mocking RestTemplate but Response Always Null

Time:12-28

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);
  • Related