Search code examples
javajunitmockitojunit5

Getting "0 matchers expected, 1 recorded:" when I writing my Junit test case for below class


here is my class which has two methods get and exchange, I am not sure how to write test case for below two methods, since we are using "new RestTemplate(new HttpComponentsClientHttpRequestFactory()).exchange" I dont know how to mock this.

and how to write a test case for another method in same class

@Service
       public class TestServiceImpl implements TestService{


      @Override
          public Object get(String endpoint, ParameterizedTypeReference reference, boolean useToken) {
          ResponseEntity response = exchange(HttpMethod.GET, endpoint, null, reference, useToken);
           return response.getBody();
          }


      public ResponseEntity<Object> exchange(HttpMethod httpMethod, String endpoint, @Nullable                Object body, ParameterizedTypeReference<Object> reference, boolean useToken,String userId) {
 
           try {
            response = new RestTemplate(new HttpComponentsClientHttpRequestFactory()).exchange(endpoint, httpMethod, new HttpEntity<>(body, headers), reference);
            return response;
            } catch (Exception e) {
           e.printStackTrance
            }
         }
      }
      }





    @Test
     public void getTest(){
    IdmService idmService1 = Mockito.spy(idmService);
           Mockito.doReturn(TestData.getMockResponseEntity()).when(idmService1).exchange(any(),anyString(),any(),any(),anyBoolean());
      assertEquals(TestData.getMockResponseEntity().getBody(),idmService.get(endPoint,any(),true));
   }
 @Test
public void exchangeTest(){
  when(restTemplate.exchange(anyString(), ArgumentMatchers.any(HttpMethod.class),ArgumentMatchers.any(HttpEntity.class),
            ArgumentMatchers.any(HttpHeaders.class))).thenReturn(TestData.getMockResponseEntity())
    assertEquals(TestData.getMockResponseEntity().getBody(),idmService.get(endPoint,any(),true));

}

Solution

  • You can't mock RestTemplate when you create it like that.

    Instead create a factory which you can inject, and mock the factory to return a mock RestTemplate:

    @Component
    class RestTemplateFactory {
      public RestTemplate create() {
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
      }
    }
    

    Then in TestServiceImpl:

    public class TestServiceImpl implements TestService {
      private final RestTemplateFactory restTemplateFactory;
    
      @Autowired
      public TestServiceImpl(RestTemplateFactory restTemplateFactory) {
        this.restTemplateFactory = restTemplateFactory;
      }
      ...
    

    and finally in your test:

    ...
    RestTemplateFactory factory = mock(RestTemplateFactory.class);
    RestTemplate template = mock(RestTemplate.class);
    TestServiceImpl service = new TestServiceImpl(factory);
    when(factory.create()).thenReturn(template);
    when(template.exchange(...)).thenReturn(...)
    
    assertEquals(TestData.getMockResponseEntity().getBody(),service.get(...));
    ...