- RestTemplate
스프링에서 외부 api를 호출해야 할 상황이 있는 경우, 간단하게 spirng에 내장 된 restTemplate을 이용할 수 있습니다.
@Slf4j
@Transactional
@Service
public class DeliveryService {
private final DeliveryRepository deliveryRepository;
private final RestTemplate restTemplate;
private static String serverUrl;
private final BalanceHistoryRepository balanceHistoryRepository;
private final DeliveryRepositorySupport deliveryRepositorySupport;
@Value("${restApiUrl}")
public void setServerUrl(String serverUrl) {
DeliveryService.serverUrl = serverUrl;
}
public DeliveryService(DeliveryRepository deliveryRepository, RestTemplateBuilder restTemplateBuilder, BalanceHistoryRepository balanceHistoryRepository, DeliveryRepositorySupport deliveryRepositorySupport) {
this.deliveryRepository = deliveryRepository;
this.restTemplate = restTemplateBuilder.build();
this.balanceHistoryRepository = balanceHistoryRepository;
this.deliveryRepositorySupport = deliveryRepositorySupport;
}
public String deliveryStart(DeliveryCreate dto,Rider rider) {
Delivery delivery = Delivery.create(rider,dto);
deliveryRepository.save(delivery);
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(serverUrl +"/delivery/start");
DeliveryStartReq request = new DeliveryStartReq(delivery);
return restTemplate.postForObject(builder.toUriString(),request,String.class);
}
위 코드는 단순하게 엔티티를 만들어서 저장하고, restTemplate을 이용하여 dto를 외부 api로 post 전송하는 서비스단 코드입니다.
※ Spring Framework 5부터는 WebFlux 스택과 함께 Spring은 WebClient 라는 새로운 HTTP 클라이언트를 도입하여 기존의 동기식 API를 제공할 뿐 만 아니라 효율적인 비차단 및 비동기 접근 방식을 지원하여, Spring 5.0 이후 부터는 RestTemplate는 deprecated 되었습니다. (WebClient 사용 지향)
위와 같이 외부의 api 연동에 대한 테스트 코드를 작성하려는 경우엔 어떻게 해야할까요?
@RestClientTest

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing
RestTemplate을 이용했을 경우,@RestClientTest어노테이션을 이용하여 테스트를 진행 할 수 있습니다.
@RestClientTest를 이용할 경우,
- 외부 API를 MOCKING 할 수 있습니다.
- MockRestServiceServer라는 임시 서버를 Bean으로 생성해줍니다.
- 서비스 테스트 코드
@RestClientTest(value = DeliveryService.class)
class DeliveryServiceTest {
@Autowired
DeliveryService deliveryService;
@MockBean
DeliveryRepository deliveryRepository;
@MockBean
BalanceHistoryRepository balanceHistoryRepository;
@MockBean
DeliveryRepositorySupport deliveryRepositorySupport;
@Autowired
private MockRestServiceServer mockServer;
@Test
@DisplayName("운행 시작 성공")
void deliveryStart() {
//given
Rider rider = Rider.builder()
.name("test")
.driverId("GG1234")
.build();
DeliveryCreate req = DeliveryCreate.builder()
.receiveId("20220928dsd")
.clientName("맥도날드")
.requestTime("2022-09-28 14:25:47")
.appointTime("2022-09-28 14:26:00")
.build();
String expectedApiUrl = "http://localhost/delivery/start";
String expectedJsonResponse = "ok";
mockServer.expect(requestTo(expectedApiUrl))
.andExpect(method(HttpMethod.POST))
.andRespond(withSuccess(expectedJsonResponse, MediaType.APPLICATION_JSON));
//when
String result = deliveryService.deliveryStart(req, rider);
//then
assertThat(result).isEqualTo("ok");
}
MockRestServiceServer의 expect(requestTo(...)) 메소드를 이용해서 서비스단에서 설정한 url과 테스트 요청 url이 일치하는지 확인할 수 있으며, method()와 andRespond() 메소드를 이용해서 http메소드와 응답값을 검증할 수 있습니다.
( 위 코드의 경우 단순하게 응답 값이 String "ok"일 경우 정상적으로 테스트를 통과할 수 있습니다. )
mockServer.expect(requestTo(expectedApiUrl))
.andExpect(method(HttpMethod.POST))
.andRespond(withSuccess(expectedJsonResponse, MediaType.APPLICATION_JSON));
※ 주의
Parameter 1 of constructor in jjfactory.simpleapi.business.delivery.service.DeliveryService required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found.
RestTemplate은 Mocking되지 않는다는 단점이 있습니다. 따라서 서비스단에서 restTemplate이아닌 restTemplateBuilder를 이용해주셔야 위와같은 에러코드를 만나지 않을 수 있습니다!
public DeliveryService(DeliveryRepository deliveryRepository, RestTemplateBuilder restTemplateBuilder, BalanceHistoryRepository balanceHistoryRepository, DeliveryRepositorySupport deliveryRepositorySupport) {
this.deliveryRepository = deliveryRepository;
this.restTemplate = restTemplateBuilder.build();
this.balanceHistoryRepository = balanceHistoryRepository;
this.deliveryRepositorySupport = deliveryRepositorySupport;
}
다음 시간에는 deprecated 된 restTemplate이 아닌, webClient를 이용한 클라이언트 요청과 그 테스트를 하는 방법을 알아보도록 하겠습니다.
- 참고
https://blog.naver.com/hj_kim97/222295259904
[Spring]스프링 RestTemplate
스프링 RestTemplate - RestTemplate란? - RestTemplate의 특징 - RestTemplate 동작 원리 - AP...
blog.naver.com
https://jojoldu.tistory.com/341
Spring Boot에서 외부 API 테스트하기
안녕하세요? 이번 시간엔 Spring Boot의 @RestClientTest 예제를 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. 1. 문제 상황 예를 들어 외부 API를
jojoldu.tistory.com
'테스트' 카테고리의 다른 글
| 테스트 픽스처 (스프링 캠프 2024) (1) | 2024.09.13 |
|---|---|
| @RequestPart 테스트 (1) | 2022.10.06 |
| 쿼리 dsl 테스트 코드작성 (0) | 2022.09.22 |
| @AuthenticationPrincipal 테스트하기 (0) | 2022.07.18 |
| @JdbcTest (0) | 2022.06.23 |