Open lightbell03 opened 1 year ago
아직 스토어 쪽에 배송 호출이나 콜백 받는 기능이 없어 통합테스트를 작성해보았다. 테스트를 작성하면서 겪었던 애로사항들을 정리.
@RestController
@RequestMapping("/test/callback")
@Slf4j
public class CallbackTestController {
@PostMapping
public CallbackResponse returnCallbackResponse(@RequestBody CallbackResponse callbackResponse) {
log.info("callbackResponse : {}", callbackResponse.toString());
return callbackResponse;
}
}
먼저 위와 같은 클래스를 테스트쪽에 작성하여 해당 콜백이 되는지 확인해보고 싶었다.
``` java
// ... 생략
DeliveryRequestRequest deliveryRequestRequest = new DeliveryRequestRequest();
ReflectionTestUtils.setField(deliveryRequestRequest, "deliveryAddress", "배달 주소");
ReflectionTestUtils.setField(deliveryRequestRequest, "price", 5000);
ReflectionTestUtils.setField(deliveryRequestRequest, "reqStore", "가게1");
ReflectionTestUtils.setField(deliveryRequestRequest, "reqStoreAddress", "가게 주소");
ReflectionTestUtils.setField(deliveryRequestRequest, "prepDatetime", LocalDateTime.now());
ReflectionTestUtils.setField(deliveryRequestRequest, "reqMemo", "메모");
ReflectionTestUtils.setField(deliveryRequestRequest, "callbackId", "123");
ReflectionTestUtils.setField(deliveryRequestRequest, "callbackUrl", "http://local.baegopa.store:8086/test/callback");
mockMvc.perform(post("/delivery")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(deliveryRequestRequest)))
.andDo(print())
.andExpect(status().isOk());
// ... 생략
여기서 local.baegopa.store는 127.0.0.1 을 hosts에 등록 한 것이다.
위 테스트 코드를 실행하면 CallbackTestController에서 log가 찍혀야하는데 계속 오류가 나왔다.
해당 오류는 RestTemplate 가 http://local.baegopa.store:8086/test/callback 를 찾지 못해서 발생.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
위와같이 랜덤 포트를 지정시키고 아래처럼 port를 받아오거나
@LocalServerPort
private int port;
내가 지정한 포트로 실행하게끔 아래처럼 해야한다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
처음에는 Thread.sleep() 기능을 이용하여 무작정 대기시키고 DB에 데이터가 정상적으로 진행 됐는지 확인을 진행하였다. 그랬더니 소나큐브에서 경고를 주었다. 소나큐브가 제시한 방법은 await() 를 사용하라 였다.
아래 라이브러리를 사용하면 편하게 비동기, 멀티쓰레드 테스트를 진행 할 수 있다.
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
await()
.atMost(Duration.ofMinutes(1)) // 최대 1분까지
.pollInterval(Duration.ofSeconds(5)) // 5초 간격으로 검사
.until(() -> { // true 가 뜰 때까지 검사
DeliveryInfoEntity deliveryInfoEntity = deliveryInfoRepository.findAll().get(0);
DeliveryStateCode stateCode = deliveryStateHistoryRepository.findAll(Example.of(DeliveryStateHistoryEntity.builder()
.deliveryInfoEntity(deliveryInfoEntity)
.build()), Sort.by(Sort.Direction.DESC, "createDatetime"))
.get(0)
.getDeliveryStateCode();
log.info("stateCode : {}, {}", stateCode, stateCode.getName());
return DeliveryStateCode.A6.equals(stateCode) // 거절이거나
|| DeliveryStateCode.A5.equals(stateCode) // 취소이거나
|| DeliveryStateCode.A4.equals(stateCode); // 배송완료이면
});
전체적인 배송 시스템은 더미 시스템 이다.
지금은 더미 시스템이지만 추후 실제로 기사 매칭이나 배송진행 시스템이 들어 올 것을 대비하여 서비스 구조를 아래처럼 가져갔다.