Невозможно издеваться над конструктором RestTemplate

#java #spring #mockito #resttemplate

#java #весна #mockito #resttemplate

Вопрос:

У меня есть метод интерфейса write по умолчанию, и я хочу его протестировать, но у меня ошибка junit «Сбой контекста приложения».

Мой тест:

 @RunWith(SpringRunner.class)
@SpringBootTest(classes = {SecurityCodeRepository.class})
public class SecurityCodeRepositoryTest {
    @Autowired
    private SecurityCodeRepository repo;

    @Spy
    private CustomClientHttpRequestFactory factory;

    @Mock
    private RestTemplate restTemplate;

    @Test
    public void testRepoWhenResponse() {
        // INIT
        final SecurityCodeIn wo = new SecurityCodeIn("123458");
        final ResponseEntity<SecurityCodeOut> responseEntity = new ResponseEntity<>(new SecurityCodeOut(true, false), HttpStatus.OK);
        when(restTemplate.exchange(anyString(),
                any(HttpMethod.class),
                any(HttpEntity.class), any(Class.class), anyString())).thenReturn(responseEntity);

        // PROCESS
        final SecurityCodeOut out = repo.callWS(wo, "urlWs", HttpMethod.POST, new SecurityCheckErrorHandler(), SecurityCodeOut.class,
                "ff32223b-bde5-4d60-a21d-4e3e01dcd416");

        // CHECKS
        assertTrue(out.isRetry());
        assertFalse(out.isStatus());
    }

}
  

Мой репозиторий для тестирования :

     @Repository
public class SecurityCodeRepository implements GenericRepository<SecurityCodeIn, SecurityCodeOut> {

    /**
     * Error LOGGER.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityCodeRepository.class);

    /** The x caller key. */
    @Value("${service.x-caller-key}")
    private String xCallerKey;

    /** The Constant APP_CALLER_KEY. */
    private static final String APP_CALLER_KEY = "App-caller-key";

    @Autowired
    private CustomClientHttpRequestFactory factory;

    @Override
    public HttpHeaders getHeader() {
        final HttpHeaders headersCompleted = new HttpHeaders();
        headersCompleted.setContentType(MediaType.APPLICATION_JSON);
        headersCompleted.set(APP_CALLER_KEY, xCallerKey);

        return headersCompleted;
    }

    @Override
    public Logger getLogger() {
        return LOGGER;
    }

    @Override
    public CustomClientHttpRequestFactory getFactory() {
        return this.factory;
    }
}
  

Мой интерфейс :

 public interface GenericRepository<I extends Object, O extends Object> {
    HttpHeaders getHeader();

    Logger getLogger();

    CustomClientHttpRequestFactory getFactory();

    default O callWS(final I elementIn, final String url, final HttpMethod method, final ResponseErrorHandler errorHandler, final Class<O> classe,
            final Object... paramsUrl) {
        final HttpEntity<?> httpEntity = new HttpEntity<>(elementIn, getHeader());
        ResponseEntity<O> responseEntity = null;

        // Create new restTemplate

        final RestTemplate restTemplate = new RestTemplate(getFactory().init(false));
        // add logger for debug
        restTemplate.setInterceptors(Collections.singletonList(new RequestResponseLoggingInterceptor()));

        // add process error
        restTemplate.setErrorHandler(errorHandler);

        try {
            getLogger().info("Appel du webService - {} - {}", url, method);
            responseEntity = restTemplate.exchange(url, method, httpEntity,
                    classe, paramsUrl);
        } catch (final RestClientResponseException rce) {
            getLogger().error("RestClientException - {}", url, rce);
        }

        // If there is no response, throw technical exception
        if (responseEntity == null) {
            throw new WebServiceException("Impossible de contacter l'API ".concat(url));
        }

        return responseEntity.getBody();
    }
}
  

Мой тестовый вызов моего репозитория, который реализует интерфейс и использует метод по умолчанию. Итак, этот тест должен издеваться над getFactory(). На самом деле, этот объект равен нулю в тесте junit. :/

Как я могу протестировать свой GenericRepository, издевающийся над моим RestTemplate?

Спасибо 🙂

Ответ №1:

С @SpringBootTest аннотацией Spring Boot предоставляет удобный способ запуска контекста приложения для использования в тестировании. И с помощью classes мы можем указать Spring Boot, какой класс приложения использовать для создания контекста приложения. Но вы по какой-то причине указали SecurityCodeRepository.class как classes параметр. Вы должны заменить его на Application.class или удалить вообще. Здесь вы можете найти полное объяснение