Тестовый модуль JAVA mockito для resttemplate и retryTemplate - PullRequest
0 голосов
/ 28 февраля 2019

В настоящее время я пишу модульный тест для метода ниже

@Autowired
private RequestConfig requestConfig;

@Autowired
private RetryTemplate retryTemplate;

public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
    try {
        return retryTemplate.execute(retryContext -> {

            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = requestConfig.createHttpHeaders();
            HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
            ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
            return response;

        });
    } catch (Exception e) {
        throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
    }
}

ОБНОВЛЕННЫЙ МЕТОД:

@Autowired
private RequestConfig requestConfig;

@Autowired
private RetryTemplate retryTemplate;

@Autowired
private RestTemplate restTemplate;

public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
    try {
        return retryTemplate.execute(retryContext -> {

            HttpHeaders headers = requestConfig.createHttpHeaders();
            HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
            ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
            return response;

        });
    } catch (Exception e) {
        throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
    }
}

Я испробовал все возможности, но не смог сделать это правильно.Вот мой нижеприведенный тест.

@Mock
private RestTemplate restTemplate;

@Mock
public RequestConfig requestConfig;

@InjectMocks
private RetryTemplate retryTemplate;

ServiceRequest serviceRequest;


@Test
public void makeGetServiceCall() throws Exception {
    String url = "http://localhost:8080";
    RetryTemplate mockRetryTemplate = Mockito.mock(RetryTemplate.class);
    RestTemplate mockRestTemplate = Mockito.mock(RestTemplate.class);
    ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
    Mockito.when(mockRetryTemplate.execute(ArgumentMatchers.any(RetryCallback.class), ArgumentMatchers.any(RecoveryCallback.class), ArgumentMatchers.any(RetryState.class))).thenReturn(myEntity);

    Mockito.when(mockRestTemplate.exchange(
            ArgumentMatchers.eq(url),
            ArgumentMatchers.eq(HttpMethod.GET),
            ArgumentMatchers.<HttpEntity<String>>any(),
            ArgumentMatchers.<Class<String>>any())
    ).thenReturn(myEntity);

    ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);
    Assert.assertEquals(myEntity, response);
}

ОБНОВЛЕННЫЙ ДЕЛО ТЕСТА:

 @Mock
public RequestConfig requestConfig;

@Mock
private RestTemplate restTemplate;

@Mock
private RetryTemplate retryTemplate;

@InjectMocks
ServiceRequest serviceRequest;

@Test
public void makeGetServiceCall() throws Exception {
    //given:
    String url = "http://localhost:8080";

    when(requestConfig.createHttpHeaders()).thenReturn(null);
    ResponseEntity<String> myEntity = new ResponseEntity<>( HttpStatus.ACCEPTED);
    when(retryTemplate.execute(any(RetryCallback.class), any(RecoveryCallback.class), any(RetryState.class))).thenAnswer(invocation -> {
        RetryCallback retry = invocation.getArgument(0);
        return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
    });
    when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), eq(String.class)))
            .thenReturn(myEntity);

    //when:
    ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);

    //then:
    assertEquals(myEntity, response);
}

Объект ответа, который я получаю из моего вызова метода makeGetServiceCall, всегда возвращает ноль.Когда я отлаживаю код, я вижу исключение org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ResponseEntity cannot be returned by toString() toString() should return String ошибка при resttemplate макете, где я возвращаю myEntity

Я не уверен, что мне не хватает.

1 Ответ

0 голосов
/ 02 марта 2019

Ну, вы совершили довольно много ошибок ...

  1. Я уверен, что вы хотели аннотировать private RetryTemplate retryTemplate; с помощью @Mock, а не @InjectMocks
  2. @InjectMocks должно перейти на ServiceRequest serviceRequest;
  3. Вы определяете взаимодействия для некоторых mockRetryTemplate и mockRestTemplate, которые не имеют ничего общего с serviceRequest.Вместо этого вы должны использовать @Mock -аннотированные поля для определения взаимодействий, потому что они вводятся в тестируемый объект (serviceRequest)
  4. Более того, вы обычно не можете высмеивать RestTemplate и вводитьэто в ваш ServiceRequest, потому что вы не используете инъекцию зависимостей в первую очередь для RestTemplate в ServiceRequest.Вы просто создаете его экземпляр в ServiceRequest.makeGetServiceCall
  5. . Вы определяете взаимодействие с неправильным методом в строке Mockito.when(retryTemplate.execute(....Ваше взаимодействие определяет RetryTemplate.execute(RetryCallback, RecoveryCallback, RetryState), тогда как ваш ServiceRequest использует другой метод RetryTemplate.execute(RetryCallback)
  6. Вы также должны заметить, что RetryTemplate.execute является окончательным, и поэтому вы не можете высмеять его без дополнительных усилий, как объяснено здесь.И вообще, вы должны предпочесть интерфейсы классам, например, RestOperations и RetryOperations, а не RestTemplate и RetryTemplate соответственно, чтобы быть более гибкими.

При этом ниже приведен рабочий тесткоторая решает вашу проблему.Но обратите внимание на удаление RestTemplate restTemplate = new RestTemplate(); из ServiceRequest и создание restTemplate поля, чтобы оно вводилось в зависимости.

@RunWith(MockitoJUnitRunner.class)
public class ServiceRequestTest {
    @Mock
    private RestTemplate restTemplate;

    @Mock
    public RequestConfig requestConfig;

    @Mock
    private RetryTemplate retryTemplate;

    @InjectMocks
    ServiceRequest serviceRequest;

    @Test
    public void makeGetServiceCall() throws Exception {
        //given:
        String url = "http://localhost:8080";
        ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
        when(retryTemplate.execute(any(RetryCallback.class))).thenAnswer(invocation -> {
            RetryCallback retry = invocation.getArgument(0);
            return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
        });
        when(restTemplate.exchange(eq(url), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class)))
                .thenReturn(myEntity);

        //when:
        ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);

        //then:
        assertEquals(myEntity, response);
    }
}
...