На самом деле это то, что вы хотите смоделировать:
restTemplateConfig.getRestTemplate().exchange(eVerifyGovernmentProperties.getUrl(), HttpMethod.GET, null, String.class);
, но это потребует глубокой насмешки, и это тоже неприятный запах: вам не нужно определять такое утверждение для вызова шаблона rest.Эта ответственность должна быть определена в определенном классе.
Так что перенесите его в метод определенного компонента, например RestTemplateService
, который избавит вас от передачи стольких параметров, а также уравновесит лучшую ответственность этого класса за счет сокращенияего зависимости:
ResponseEntity<String> healthResponse = restTemplateService.getForHealthCheck();
Теперь просто смоделируйте его с помощью Mockito.
Что касается RestTemplateService
, вы можете создать свой собственный класс или полагаться на Feign (здесь Spring Feign имеет больше смысла), который включает декларативный отдых клиента через интерфейс.
Это даст:
public class HealthStatusImpl implements HealthStatus {
private RestTemplateService restTemplateService;
// favor constructor injection
public HealthStatusImpl(RestTemplateService restTemplateService){
this.restTemplateService = restTemplateService;
}
@Override
public Integer healthCheck() {
Integer status = 0;
try {
ResponseEntity<String> healthResponse = restTemplateService.getForHealthCheck();
status = healthResponse.getStatusCode().is2xxSuccessful() ? 200 : 400;
} catch (Throwable th) {
th.printStackTrace();
}
return status;
}
}
Обратите внимание, что Status.is2xxSuccessful()
, как правило, лучше, так как возвращает значение true для любого успешного ответа (200
, 201
и т. Д.).И если это не удастся, вы хотите вернуть код ответа об ошибке.
Со стороны модульного тестирования вы должны смоделировать эту зависимость и записать ложное поведение в соответствии с вашими сценариями.
Обратите внимание, что в вашем случае вы не хотите загружать весь контекст пружины, но вы хотитевыполнить простой модульный тест, то есть без контейнера.Так что не используйте @SpringBootTest
, а только JUnit и Mockito.
Например, с JUnit 5:
@ExtendWith(MockitoExtension.class)
public class HealthStatusImplTest{
private HealthStatusImpl healthStatusImpl;
@Mock
private RestTemplateService restTemplateServiceMock;
@BeforeEach
public void beforeEach(){
healthStatusImpl = new HealthStatusImpl(restTemplateService);
}
@Test
public void healthCheck_when_200_is_returned(){
Mockito.when(restTemplateServiceMock)
.getForHealthCheck().thenReturn(new ResponseEntity(HttpStatus.OK));
assertEquals(200, healthStatusImpl.healthCheck());
}
@Test
public void healthCheck_when_200_is_not_returned(){
Mockito.when(restTemplateServiceMock)
.getForHealthCheck().thenReturn(new ResponseEntity(HttpStatus.NOT_FOUND));
assertEquals(400, healthStatusImpl.healthCheck());
}
}
Конечно, RestTemplateService
также должен быть унитарным тестом, и унитарные тесты не освобождают от написания интеграционных тестов для компонентов более высокого уровня.