diff --git a/.gitignore b/.gitignore index 55d456f..a0fd69e 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,7 @@ magick ### macOS ### .DS_Store -/**/.DS_Store \ No newline at end of file +/**/.DS_Store + +### QFile ### +**/src/main/generated/**/Q*.java \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index fbfd710..d7b157c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,8 @@ [submodule "application/wypl-image/src/main/resources/security"] path = application/wypl-image/src/main/resources/security url = https://github.com/What-s-Your-Plan/wypl-image-properties.git - branch = main \ No newline at end of file + branch = main +[submodule "application/wypl-core/src/main/resources/security"] + path = application/wypl-core/src/main/resources/security + url = https://github.com/What-s-Your-Plan/wypl-server-properties + branch = main diff --git a/application/wypl-core/build.gradle b/application/wypl-core/build.gradle index a5baadb..2195757 100644 --- a/application/wypl-core/build.gradle +++ b/application/wypl-core/build.gradle @@ -9,6 +9,7 @@ java { dependencies { implementation project(':application:application-common') + implementation project(':client:openweather-client') implementation project(':domain:jpa-common') implementation project(':domain:mongo-common') implementation project(':domain:jpamongo-review-domain') diff --git a/application/wypl-core/src/main/java/com/wypl/wyplcore/config/RestTemplateConfig.java b/application/wypl-core/src/main/java/com/wypl/wyplcore/config/RestTemplateConfig.java new file mode 100644 index 0000000..160cdf0 --- /dev/null +++ b/application/wypl-core/src/main/java/com/wypl/wyplcore/config/RestTemplateConfig.java @@ -0,0 +1,14 @@ +package com.wypl.wyplcore.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/application/wypl-core/src/main/resources/application.yml b/application/wypl-core/src/main/resources/application.yml index dc9bdc2..1043a55 100644 --- a/application/wypl-core/src/main/resources/application.yml +++ b/application/wypl-core/src/main/resources/application.yml @@ -1,25 +1,14 @@ spring: application: name: wypl-core - jpa: - properties: - hibernate: - show_sql: true - format_sql: true - hibernate: - ddl-auto: create-drop - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:db - username: sa - password: - h2: - console: - enabled: true - path: /h2 - -de: - flapdoodle: - mongodb: - embedded: - version: 4.0.2 + config: + import: + - security/application-mongo.yml + - security/application-oracle.yml + - security/application-weather.yml + activate: + on-profile: + - default + - local + - dev + - prod \ No newline at end of file diff --git a/application/wypl-core/src/main/resources/security b/application/wypl-core/src/main/resources/security new file mode 160000 index 0000000..2a6e5aa --- /dev/null +++ b/application/wypl-core/src/main/resources/security @@ -0,0 +1 @@ +Subproject commit 2a6e5aa2d2dc019e371f919a875147c6956690bf diff --git a/client/openweather-client/build.gradle b/client/openweather-client/build.gradle index b5e47f5..6e116b4 100644 --- a/client/openweather-client/build.gradle +++ b/client/openweather-client/build.gradle @@ -5,4 +5,57 @@ java { } dependencies { -} \ No newline at end of file + implementation project(':common') + + implementation('org.springframework.boot:spring-boot-starter') + implementation('org.springframework.boot:spring-boot-starter-web') + + testImplementation('org.springframework.boot:spring-boot-starter-test') + testImplementation('org.mockito:mockito-core') +} + +/* Jacoco Start */ +tasks.withType(JacocoReport).configureEach { + reports { + html.required.set(true) + xml.required.set(true) + html.outputLocation.set(file("reports/jacoco/index.xml")) + xml.outputLocation.set(file("reports/jacoco/test/jacocoTestReport.xml")) + } + + classDirectories.setFrom( + files(classDirectories.files.collect { + fileTree(it) { + exclude( + "**/config/**", + "**/data/**", + "**/exception/**", + "**/type/**", + ) + } + }) + ) +} + +tasks.jacocoTestCoverageVerification { + violationRules { + rule { + enabled = true + element = 'CLASS' + + limit { + counter = 'LINE' + value = 'COVEREDRATIO' + minimum = 0.80D + } + + excludes = [ + "**/config/**", + "**/data/**", + "**/exception/**", + "**/type/**", + ] + } + } +} +/* Jacoco End */ \ No newline at end of file diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/.gitkeep b/client/openweather-client/src/main/java/com/wypl/openweatherclient/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClient.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClient.java new file mode 100644 index 0000000..3907b40 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClient.java @@ -0,0 +1,8 @@ +package com.wypl.openweatherclient; + +import com.wypl.openweatherclient.data.OpenWeatherCond; +import com.wypl.openweatherclient.data.OpenWeatherResponse; + +public interface OpenWeatherClient { + OpenWeatherResponse fetchWeather(OpenWeatherCond cond); +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClientImpl.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClientImpl.java new file mode 100644 index 0000000..cecf6e1 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherClientImpl.java @@ -0,0 +1,46 @@ +package com.wypl.openweatherclient; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import com.wypl.openweatherclient.config.OpenWeatherProperties; +import com.wypl.openweatherclient.data.OpenWeatherCond; +import com.wypl.openweatherclient.data.OpenWeatherResponse; +import com.wypl.openweatherclient.exception.OpenWeatherErrorCode; +import com.wypl.openweatherclient.exception.OpenWeatherException; + +import lombok.RequiredArgsConstructor; + +@EnableConfigurationProperties(OpenWeatherProperties.class) +@RequiredArgsConstructor +@Component +public class OpenWeatherClientImpl implements OpenWeatherClient { + + private final RestTemplate restTemplate; + private final OpenWeatherProperties properties; + + public OpenWeatherResponse fetchWeather(OpenWeatherCond cond) { + String url = OpenWeatherUrlFactory.create(properties.getBaseUrl(), properties.getKey()) + .weatherRegion(cond.city()) + .isLangKr(cond.isLangKr()) + .isMetric(cond.isMetric()) + .build(); + + ResponseEntity response = restTemplate.getForEntity( + url, + OpenWeatherResponse.class + ); + + HttpStatusCode httpStatusCode = response.getStatusCode(); + if (httpStatusCode.is2xxSuccessful()) { + return response.getBody(); + } + if (httpStatusCode.is5xxServerError()) { + throw new OpenWeatherException(OpenWeatherErrorCode.INTERNAL_SERVER_ERROR); + } + throw new OpenWeatherException(OpenWeatherErrorCode.INVALID_OPEN_WEATHER_REQUEST); + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherUrlFactory.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherUrlFactory.java new file mode 100644 index 0000000..f5bdfea --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/OpenWeatherUrlFactory.java @@ -0,0 +1,41 @@ +package com.wypl.openweatherclient; + +import com.wypl.openweatherclient.type.WeatherRegion; + +public class OpenWeatherUrlFactory { + + private final StringBuilder url; + + private OpenWeatherUrlFactory(String baseUrl, String key) { + this.url = new StringBuilder(baseUrl).append("?appid=").append(key); + } + + public static OpenWeatherUrlFactory create(String baseUrl, String key) { + return new OpenWeatherUrlFactory(baseUrl, key); + } + + public OpenWeatherUrlFactory weatherRegion(WeatherRegion weatherRegion) { + url.append("&q=").append(weatherRegion.getCityEn()); + return this; + } + + public OpenWeatherUrlFactory isLangKr(boolean isLangKr) { + url.append("&lang="); + if (isLangKr) { + url.append("kr"); + } + return this; + } + + public OpenWeatherUrlFactory isMetric(boolean isMetric) { + url.append("&units="); + if (isMetric) { + url.append("metric"); + } + return this; + } + + public String build() { + return url.toString(); + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/config/OpenWeatherProperties.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/config/OpenWeatherProperties.java new file mode 100644 index 0000000..1911f3e --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/config/OpenWeatherProperties.java @@ -0,0 +1,14 @@ +package com.wypl.openweatherclient.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import lombok.Getter; +import lombok.Setter; + +@ConfigurationProperties(prefix = "open-weather") +@Getter +@Setter +public class OpenWeatherProperties { + private String key; + private String baseUrl; +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherCond.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherCond.java new file mode 100644 index 0000000..91c3bee --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherCond.java @@ -0,0 +1,23 @@ +package com.wypl.openweatherclient.data; + +import com.wypl.openweatherclient.type.WeatherRegion; + +public record OpenWeatherCond( + WeatherRegion city, + boolean isMetric, + boolean isLangKr +) { + public static OpenWeatherCond fromCity( + final WeatherRegion city + ) { + return new OpenWeatherCond(city, true, true); + } + + public static OpenWeatherCond of( + final WeatherRegion city, + final boolean isMetric, + final boolean isLangKr + ) { + return new OpenWeatherCond(city, isMetric, isLangKr); + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherResponse.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherResponse.java new file mode 100644 index 0000000..8e29af2 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/data/OpenWeatherResponse.java @@ -0,0 +1,100 @@ +package com.wypl.openweatherclient.data; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record OpenWeatherResponse( + @JsonProperty("weather") + List weather, + @JsonProperty("main") + MainResponse main, + @JsonProperty("sys") + SysResponse sys, + @JsonProperty("dt") + long dateTime +) { + + public static WeatherResponse of( + final int id, + final String main, + final String desc + ) { + return new WeatherResponse(id, main, desc); + } + + public static MainResponse of( + final float temp, + final float maxTemp, + final float minTemp + ) { + return new MainResponse(temp, maxTemp, minTemp); + } + + public static SysResponse of( + final long sunrise, + final long sunset + ) { + return new SysResponse(sunrise, sunset); + } + + public int getWeatherId() { + return weather.get(0).id(); + } + + public String getWeatherName() { + return weather.get(0).main(); + } + + public String getWeatherDescription() { + return weather.get(0).description(); + } + + public float getTemperature() { + return main.temp(); + } + + public float getMaxTemperature() { + return main.maxTemp(); + } + + public float getMinTemperature() { + return main.minTemp(); + } + + public long getSunrise() { + return sys.sunrise(); + } + + public long getSunset() { + return sys.sunset(); + } + + public record WeatherResponse( + @JsonProperty("id") + int id, + @JsonProperty("main") + String main, + @JsonProperty("description") + String description + ) { + } + + public record MainResponse( + @JsonProperty("temp") + float temp, + @JsonProperty("temp_max") + float maxTemp, + @JsonProperty("temp_min") + float minTemp + ) { + } + + public record SysResponse( + @JsonProperty("sunrise") + long sunrise, + @JsonProperty("sunset") + long sunset + ) { + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherErrorCode.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherErrorCode.java new file mode 100644 index 0000000..27f8836 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherErrorCode.java @@ -0,0 +1,21 @@ +package com.wypl.openweatherclient.exception; + +import com.wypl.common.exception.ServerErrorCode; + +import lombok.Getter; + +@Getter +public enum OpenWeatherErrorCode implements ServerErrorCode { + INVALID_OPEN_WEATHER_REQUEST(500, "OPEN_WEATHER_001", "외부 서비스의 오류입니다."), + INTERNAL_SERVER_ERROR(400, "OPEN_WEATHER_002", "올바르지 않은 요청입니다."); + + private final int statusCode; + private final String errorCode; + private final String message; + + OpenWeatherErrorCode(int statusCode, String errorCode, String message) { + this.statusCode = statusCode; + this.errorCode = errorCode; + this.message = message; + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherException.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherException.java new file mode 100644 index 0000000..0e6d685 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/exception/OpenWeatherException.java @@ -0,0 +1,9 @@ +package com.wypl.openweatherclient.exception; + +import com.wypl.common.exception.WyplException; + +public class OpenWeatherException extends WyplException { + public OpenWeatherException(OpenWeatherErrorCode serverErrorCode) { + super(serverErrorCode); + } +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherRegion.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherRegion.java new file mode 100644 index 0000000..cd69ab8 --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherRegion.java @@ -0,0 +1,17 @@ +package com.wypl.openweatherclient.type; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum WeatherRegion { + KOREA("Asia/Seoul", "Seoul", "서울"), + WEST_USA("America/Los_Angeles", "Los Angeles", "로스엔젤레스"), + EAST_USA("America/New_York", "New York", "뉴욕"), + ENGLAND("Europe/London", "London", "런던"); + + private final String timeZone; + private final String cityEn; + private final String cityKr; +} diff --git a/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherType.java b/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherType.java new file mode 100644 index 0000000..27a7e4c --- /dev/null +++ b/client/openweather-client/src/main/java/com/wypl/openweatherclient/type/WeatherType.java @@ -0,0 +1,35 @@ +package com.wypl.openweatherclient.type; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import lombok.AllArgsConstructor; +import lombok.Generated; +import lombok.Getter; + +/** + * OPEN WEATHER ID + */ +@Generated +@AllArgsConstructor +@Getter +public enum WeatherType { + CLEAR(1, new HashSet<>(List.of(800)), "맑음"), + CLOUDS(2, new HashSet<>(List.of(801, 802, 803, 804)), "구름"), + RAIN(3, new HashSet<>(List.of(500, 501, 502, 503, 504, 511, 520, 521, 522, 531)), "비"), + DRIZZLE(4, new HashSet<>(List.of(300, 301, 302, 310, 311, 312, 313, 314, 321)), "이슬비"), + SNOW(5, new HashSet<>(List.of(600, 601, 602, 611, 612, 613, 615, 616, 620, 621, 622)), "눈"), + MIST(6, new HashSet<>(List.of(701, 711, 721, 731, 741, 751, 761, 762)), "안개"), + SQUALL(7, new HashSet<>(List.of(771)), "스콜"), + TORNADO(8, new HashSet<>(List.of(781)), "태풍"), + THUNDERSTORM(9, new HashSet<>(List.of(200, 201, 202, 210, 211, 212, 221, 230, 231, 232)), "천둥"); + + private final int weatherId; + private final Set ids; + private final String description; + + public boolean containsIds(final int weatherId) { + return ids.contains(weatherId); + } +} diff --git a/client/openweather-client/src/main/resources/application.yml b/client/openweather-client/src/main/resources/application.yml deleted file mode 100644 index 3c90763..0000000 --- a/client/openweather-client/src/main/resources/application.yml +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=openweather-client diff --git a/client/openweather-client/src/test/java/com/wypl/openweatherclient/.gitkeep b/client/openweather-client/src/test/java/com/wypl/openweatherclient/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherClientTest.java b/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherClientTest.java new file mode 100644 index 0000000..63f91e0 --- /dev/null +++ b/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherClientTest.java @@ -0,0 +1,79 @@ +package com.wypl.openweatherclient; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.client.RestTemplate; + +import com.wypl.openweatherclient.config.OpenWeatherProperties; +import com.wypl.openweatherclient.data.OpenWeatherCond; +import com.wypl.openweatherclient.data.OpenWeatherResponse; +import com.wypl.openweatherclient.exception.OpenWeatherErrorCode; +import com.wypl.openweatherclient.exception.OpenWeatherException; +import com.wypl.openweatherclient.fixture.OpenWeatherFixture; +import com.wypl.openweatherclient.fixture.OpenWeatherResponseFixture; + +@ExtendWith(MockitoExtension.class) +class OpenWeatherClientTest { + @InjectMocks + private OpenWeatherClientImpl openWeatherClient; + + @Mock + private OpenWeatherProperties properties; + + @Mock + private RestTemplate restTemplate; + + @BeforeEach + void propertiesSetUp() { + given(properties.getBaseUrl()).willReturn("MOCK_URL"); + given(properties.getKey()).willReturn("MOCK_KEY"); + } + + @DisplayName("정상 응답(2xx)일 때 예외가 발생하지 않는지 검증") + @Test + void status2xxTest() { + /* Given */ + given(restTemplate.getForEntity(anyString(), eq(OpenWeatherResponse.class))) + .willReturn(OpenWeatherResponseFixture.KOREA_KR_CELSIUS.to2xxResponse()); + + /* When & Then */ + assertThatCode(() -> openWeatherClient.fetchWeather(OpenWeatherFixture.KOREA.toOpenWeatherCond())) + .doesNotThrowAnyException(); + } + + @DisplayName("알 수 없는 오류로 인한 OpenWeatherException 발생 여부 검증") + @Test + void statusErrorTest() { + /* Given */ + OpenWeatherCond openWeatherCond = OpenWeatherFixture.KOREA.toOpenWeatherCond(); + given(restTemplate.getForEntity(anyString(), eq(OpenWeatherResponse.class))) + .willReturn(OpenWeatherResponseFixture.KOREA_KR_CELSIUS.to3xxResponse()); + + /* When & Then */ + assertThatThrownBy(() -> openWeatherClient.fetchWeather(openWeatherCond)) + .isInstanceOf(OpenWeatherException.class) + .hasMessageContaining(OpenWeatherErrorCode.INVALID_OPEN_WEATHER_REQUEST.getMessage()); + } + + @DisplayName("잘못된 요청으로 인한(5xx) 시 OpenWeatherException 발생 여부 검증") + @Test + void status5xxTest() { + /* Given */ + OpenWeatherCond openWeatherCond = OpenWeatherFixture.KOREA.toOpenWeatherCond(); + given(restTemplate.getForEntity(anyString(), eq(OpenWeatherResponse.class))) + .willReturn(OpenWeatherResponseFixture.KOREA_KR_CELSIUS.to5xxResponse()); + + /* When & Then */ + assertThatThrownBy(() -> openWeatherClient.fetchWeather(openWeatherCond)) + .isInstanceOf(OpenWeatherException.class) + .hasMessageContaining(OpenWeatherErrorCode.INTERNAL_SERVER_ERROR.getMessage()); + } +} \ No newline at end of file diff --git a/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherUrlFactoryTest.java b/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherUrlFactoryTest.java new file mode 100644 index 0000000..7f79f67 --- /dev/null +++ b/client/openweather-client/src/test/java/com/wypl/openweatherclient/OpenWeatherUrlFactoryTest.java @@ -0,0 +1,35 @@ +package com.wypl.openweatherclient; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import com.wypl.openweatherclient.fixture.OpenWeatherFixture; + +class OpenWeatherUrlFactoryTest { + + private static final String OPEN_WEATHER_URL = "MOCK_URL"; + private static final String OPEN_WEATHER_KEY = "MOCK_KEY"; + + @DisplayName("다양한 날씨 지역 및 옵션에 따른 OpenWeather URL 생성 테스트") + @EnumSource(OpenWeatherFixture.class) + @ParameterizedTest + void createTest(OpenWeatherFixture fixture) { + /* Given */ + List params = fixture.urlParams(); + + /* When */ + String url = OpenWeatherUrlFactory.create(OPEN_WEATHER_URL, OPEN_WEATHER_KEY) + .weatherRegion(fixture.getWeatherRegion()) + .isMetric(fixture.isMetric()) + .isLangKr(fixture.isLangKr()) + .build(); + + /* Then */ + assertThat(url).contains(params); + } +} diff --git a/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherFixture.java b/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherFixture.java new file mode 100644 index 0000000..c8fd6e6 --- /dev/null +++ b/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherFixture.java @@ -0,0 +1,56 @@ +package com.wypl.openweatherclient.fixture; + +import java.util.ArrayList; +import java.util.List; + +import com.wypl.openweatherclient.data.OpenWeatherCond; +import com.wypl.openweatherclient.type.WeatherRegion; + +public enum OpenWeatherFixture { + KOREA(WeatherRegion.KOREA, true, true), + WEST_USA(WeatherRegion.WEST_USA, false, false), + EAST_USA(WeatherRegion.EAST_USA, false, false), + ENGLAND(WeatherRegion.ENGLAND, false, true), + ; + + private final WeatherRegion weatherRegion; + private final boolean isLangKr; + private final boolean isMetric; + + OpenWeatherFixture(WeatherRegion weatherRegion, boolean isLangKr, boolean isMetric) { + this.weatherRegion = weatherRegion; + this.isLangKr = isLangKr; + this.isMetric = isMetric; + } + + public List urlParams() { + List params = new ArrayList<>(); + if (isLangKr) { + params.add("lang=kr"); + } else { + params.add("lang"); + } + if (isMetric) { + params.add("units=metric"); + } else { + params.add("units"); + } + return params; + } + + public boolean isLangKr() { + return isLangKr; + } + + public boolean isMetric() { + return isMetric; + } + + public WeatherRegion getWeatherRegion() { + return weatherRegion; + } + + public OpenWeatherCond toOpenWeatherCond() { + return new OpenWeatherCond(weatherRegion, isMetric, isLangKr); + } +} diff --git a/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherResponseFixture.java b/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherResponseFixture.java new file mode 100644 index 0000000..84effb8 --- /dev/null +++ b/client/openweather-client/src/test/java/com/wypl/openweatherclient/fixture/OpenWeatherResponseFixture.java @@ -0,0 +1,69 @@ +package com.wypl.openweatherclient.fixture; + +import java.util.List; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import com.wypl.openweatherclient.data.OpenWeatherResponse; + +/** + * 도시_언어_도씨 + * KOREA_KR_CELSIUS + * KOREA_EN_FAHRENHEIT + */ +public enum OpenWeatherResponseFixture { + KOREA_KR_CELSIUS( + List.of(new OpenWeatherResponse.WeatherResponse(500, "Rain", "실 비")), + new OpenWeatherResponse.MainResponse(18.74f, 19.69f, 18.66f), + new OpenWeatherResponse.SysResponse(1728855542, 1728896209), + 1728905264 + ), + KOREA_EN_CELSIUS( + List.of(new OpenWeatherResponse.WeatherResponse(500, "Rain", "light rain")), + new OpenWeatherResponse.MainResponse(18.74f, 19.69f, 18.66f), + new OpenWeatherResponse.SysResponse(1728855542, 1728896209), + 1728905264 + ), + KOREA_KR_FAHRENHEIT( + List.of(new OpenWeatherResponse.WeatherResponse(500, "Rain", "실 비")), + new OpenWeatherResponse.MainResponse(291.89f, 292.84f, 291.81f), + new OpenWeatherResponse.SysResponse(1728855542, 1728896209), + 1728905264 + ), + KOREA_EN_FAHRENHEIT( + List.of(new OpenWeatherResponse.WeatherResponse(500, "Rain", "light rain")), + new OpenWeatherResponse.MainResponse(291.89f, 292.84f, 291.81f), + new OpenWeatherResponse.SysResponse(1728855542, 1728896209), + 1728905264 + ); + + private final List weather; + private final OpenWeatherResponse.MainResponse main; + private final OpenWeatherResponse.SysResponse sys; + private final long dateTime; + + OpenWeatherResponseFixture( + List weather, + OpenWeatherResponse.MainResponse main, + OpenWeatherResponse.SysResponse sys, + long dateTime + ) { + this.weather = weather; + this.main = main; + this.sys = sys; + this.dateTime = dateTime; + } + + public ResponseEntity to2xxResponse() { + return ResponseEntity.ok(new OpenWeatherResponse(weather, main, sys, dateTime)); + } + + public ResponseEntity to3xxResponse() { + return ResponseEntity.status(300).build(); + } + + public ResponseEntity to5xxResponse() { + return ResponseEntity.status(500).build(); + } +} diff --git a/settings.gradle b/settings.gradle index 2ad2849..61b3125 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,7 +9,7 @@ include ':application:wypl-image' /* Domain Module */ include ':domain' -include ':domain:jpa-common' +include ':domain:jpa-common' include ':domain:jpa-calendar-domain' include ':domain:jpa-member-domain' include ':domain:jpamongo-review-domain'