RestTemplate
- это класс, а не интерфейс, и он реализует реальный HTTP-транспорт. Оба стоят на пути написания тестируемого метода. Кроме того, тот факт, что вы создаете экземпляр класса, который имеет побочные эффекты на уровне ОС, а не вводит его, не помогает в этом случае. Таким образом, способ решить это:
- написать свой метод, основанный на интерфейсе, а не на реализации,
RestOperations
в данном случае
- внедрить экземпляр, реализующий
RestOperations
, например экземпляр RestTemplate
для производства через аргумент конструктора (предпочтительно), аргумент метода или через Supplier<RestOperations>
, определенный как поле в классе
- заменить фактический экземпляр реализацией теста или макетом в тесте. Я думаю, что для
Mockito.mock(RestOperations.class)
проще пойти, потому что RestOperations
, как и все другие интерфейсы Spring, определяет слишком много методов для написания тестовой реализации вручную
Так что в EncoderService
вы можете иметь:
private final RestOperations restClient;
public EncoderService(RestOperations restClient) {
this.restClient = restClient;
}
public ResponseEntity<Object> createNewStream(Long channelId) {
...
ResponseEntity<Object> response = restClient.postForEntity(...
...
}
А потом в EncoderServiceTest
:
ResponseEntity<Object> expectedReturnValue = ...
RestOperations testClient = mock(RestOperations.class);
doReturn(expectedReturnValue).when(testClient).postForEntity(any(), any(), anyClass());
EncoderService service = new EncoderService(testClient);
// use the service
В остальных двух случаях настройка теста точно такая же, просто вы передаете экземпляр в вызов метода вместо конструктора или перезаписываете поставщика в экземпляре EncoderService
, чтобы вернуть testClient
.
Я ответил на очень похожий вопрос о ProcessBuilder
, который также имеет побочные эффекты на уровне ОС и был создан непосредственно в тестируемом методе здесь Ошибка при попытке макета конструктора для ProcessBuilder с помощью PowerMockito Вы можете применять точно такую же тактику.