Skip to content

Commit

Permalink
refactor: RouteClient 응답 분기를 객체로 캡슐화 (#188)
Browse files Browse the repository at this point in the history
* refactor: RouteClient 응답 분기를 객체로 캡슐화

* chore: 패키지 디렉토리 변경

domain > dto

* refactor : 응답 매핑 로직을 mapper로 이전

* refactor : 불필요한 static 객체 삭제

* refactor : 500에러 처리 로직 추가

* refactor : NPE 예외 처리

* refactor : 롬복으로 private 생성자 구현

* test: OdsayResponseMapperTest 작성

* style: message 개행 변경

Co-authored-by: H <[email protected]>

* refactor: OdsayRouteClient에 mapper 로직 반영

* fix: FutureOrPresentDateTimeValidatorTest 오류 개선

---------

Co-authored-by: coli-geonwoo <[email protected]>
Co-authored-by: H <[email protected]>
  • Loading branch information
3 people authored Aug 1, 2024
1 parent a08b156 commit 188d651
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 31 deletions.
2 changes: 1 addition & 1 deletion backend/src/main/java/com/ody/route/domain/RouteTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@Getter
public class RouteTime {

public static final RouteTime ZERO = new RouteTime(0);
public static final RouteTime ZERO = new RouteTime(0L);

private final long minutes;
}
1 change: 0 additions & 1 deletion backend/src/main/java/com/ody/route/dto/OdsayResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import java.util.OptionalLong;

public record OdsayResponse(

Optional<String> code,
Optional<String> message,
OptionalLong minutes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.ody.route.mapper;

import com.ody.common.exception.OdyBadRequestException;
import com.ody.common.exception.OdyServerErrorException;
import com.ody.route.dto.OdsayResponse;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class OdsayResponseMapper {

private static final String CLOSE_LOCATION_CODE = "-98"; //출발지-도착지가 700m 이내일 때
private static final String ODSAY_SERVER_ERROR = "500";
private static final String EMPTY_MESSAGE = "";
private static final long ZERO_TIME = 0L;

public static long mapMinutes(OdsayResponse response) {
if (response == null) {
throw new OdyServerErrorException("response is null");
}

if (isCloseLocation(response)) {
return ZERO_TIME;
}

if(response.code().isPresent()) {
checkOdsayException(response);
}

return response.minutes().orElseThrow(() -> {
log.error("OdsayResponse minutes is Empty: {}", response);
return new OdyServerErrorException("서버 에러");
});
}

private static boolean isCloseLocation(OdsayResponse response) {
Optional<String> code = response.code();
return code.isPresent() && CLOSE_LOCATION_CODE.equals(code.get());
}

private static void checkOdsayException(OdsayResponse response) {
if (isServerErrorCode(response)) {
log.error("ODsay 500 에러: {}", response);
throw new OdyServerErrorException("서버 에러");
}

throw new OdyBadRequestException(
response.message()
.orElse(EMPTY_MESSAGE)
);
}

private static boolean isServerErrorCode(OdsayResponse response) {
Optional<String> code = response.code();
return code.isPresent() && ODSAY_SERVER_ERROR.equals(code.get());
}
}
25 changes: 3 additions & 22 deletions backend/src/main/java/com/ody/route/service/OdsayRouteClient.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package com.ody.route.service;

import com.ody.common.exception.OdyBadRequestException;
import com.ody.common.exception.OdyServerErrorException;
import com.ody.meeting.domain.Location;
import com.ody.route.config.RouteProperties;
import com.ody.route.domain.RouteTime;
import com.ody.route.dto.OdsayResponse;
import com.ody.route.mapper.OdsayResponseMapper;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.client.RestClient;

Expand Down Expand Up @@ -56,25 +55,7 @@ private URI makeURI(Location origin, Location target) {
}

private RouteTime responseToRouteTime(OdsayResponse response) {
if (response.code().isPresent()) {
return extractRouteTimeOrThrow(response);
}
response.minutes().orElseThrow(() -> {
log.error("OdsayResponse minutes is Empty: {}", response);
return new OdyServerErrorException("서버 에러");
});
return new RouteTime(response.minutes().getAsLong());
}

private RouteTime extractRouteTimeOrThrow(OdsayResponse response) {
Optional<String> code = response.code();
if (code.isPresent() && code.get().equals("-98")) {
return RouteTime.ZERO;
}
if (code.isPresent() && code.get().equals("500")) {
log.error("ODsay 500 에러: {}", response);
throw new OdyServerErrorException("서버 에버");
}
throw new OdyBadRequestException(response.message().orElseGet(() -> ""));
long minutes = OdsayResponseMapper.mapMinutes(response);
return new RouteTime(minutes);
}
}
2 changes: 1 addition & 1 deletion backend/src/main/resources/private
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jakarta.validation.Payload;
import java.lang.annotation.Annotation;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -83,14 +84,15 @@ void isValid(LocalDate date, LocalTime time, boolean expected) {
}

private static Stream<Arguments> dateTimeTestCases() {
LocalDate today = LocalDate.now();
LocalTime currentTime = LocalTime.now();
LocalDateTime now = LocalDateTime.now();
LocalDateTime beforeHour = LocalDateTime.now().minusHours(1L);
LocalDateTime afterHour = LocalDateTime.now().plusHours(1L);

return Stream.of(
Arguments.of(today, currentTime, false),
Arguments.of(today, currentTime.plusHours(1), true),
Arguments.of(today, currentTime.minusHours(1), false),
Arguments.of(today.plusDays(1), currentTime, true)
Arguments.of(now.toLocalDate(), now.toLocalTime(), false),
Arguments.of(afterHour.toLocalDate(), afterHour.toLocalTime(), true),
Arguments.of(beforeHour.toLocalDate(), beforeHour.toLocalTime(), false),
Arguments.of(now.toLocalDate().plusDays(1L), now.toLocalTime(), true)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.ody.route.mapper;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.ody.common.exception.OdyBadRequestException;
import com.ody.common.exception.OdyServerErrorException;
import com.ody.route.dto.OdsayResponse;
import java.util.Optional;
import java.util.OptionalLong;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class OdsayResponseMapperTest {

@DisplayName("소요시간을 반환한다")
@Test
void mapMinutesSuccess() {
OdsayResponse validResponse = new OdsayResponse(
Optional.empty(),
Optional.empty(),
OptionalLong.of(3L)
);

assertThat(OdsayResponseMapper.mapMinutes(validResponse))
.isEqualTo(3L);
}

@DisplayName("출, 도착지가 700m 이내일 때 0분을 반환한다")
@Test
void mapZeroMinutesWhenCloseLocation() {
OdsayResponse closeLocationResponse = new OdsayResponse(
Optional.of("-98"),
Optional.of("출,도착지가 700m 이내 입니다"),
OptionalLong.empty()
);

assertThat(OdsayResponseMapper.mapMinutes(closeLocationResponse))
.isEqualTo(0L);
}

@DisplayName("예외 응답 : 500 에러 코드는 OdyServerErrorException을 던진다")
@Test
void mapMinutes500Fail() {
OdsayResponse serverExceptionResponse = new OdsayResponse(
Optional.of("500"),
Optional.of("서버 에러 발생"),
OptionalLong.empty()
);

assertThatThrownBy(() -> OdsayResponseMapper.mapMinutes(serverExceptionResponse))
.isInstanceOf(OdyServerErrorException.class);
}

@DisplayName("예외 응답 : 그 외 에러 코드는 OdyBadRequestException을 던진다")
@Test
void mapMinutes400Fail() {
OdsayResponse badRequestExceptionException = new OdsayResponse(
Optional.of("1"),
Optional.of("그 외 에러 발생"),
OptionalLong.empty()
);

assertThatThrownBy(() -> OdsayResponseMapper.mapMinutes(badRequestExceptionException))
.isInstanceOf(OdyBadRequestException.class);
}

@DisplayName("response가 null인 경우 OdyServerErrorException을 던진다")
@Test
void nullCheck500Fail() {
assertThatThrownBy(() -> OdsayResponseMapper.mapMinutes(null))
.isInstanceOf(OdyServerErrorException.class);
}

@DisplayName("예외 응답 : 에러 코드와 소요시간이 모두 없는 경우 OdyServerException을 던진다")
@Test
void noneDataResponse500Fail() {
OdsayResponse unValidResponse = new OdsayResponse(
Optional.empty(),
Optional.empty(),
OptionalLong.empty()
);
assertThatThrownBy(() -> OdsayResponseMapper.mapMinutes(unValidResponse))
.isInstanceOf(OdyServerErrorException.class);
}
}

0 comments on commit 188d651

Please sign in to comment.