코딩블로그
TMDB OPEN API 연결 OKHTTP -> FeignClient로 변경해서 구현하기 +Test 코드 작성하기 본문
728x90
팝콘메이트에서 외부 API와 통신하는 기능이 적지 않다. 카카오와 애플은 이미 FeignClient를 이용하여 구현을 하였는데, 영화 관련 Open Api (영진위,TMDB)는 OKHTTP를 이용하여 사용하고 있다. 이미 FeignClient의 장점을 소개한 바가 있는 만큼 리팩토링을 할 때 꼭 적용해보고 싶은 부분이었다
TMDB
📙TmdbErrorDecoder
public class TmdbErrorDecoder implements ErrorDecoder {
@Override
@SneakyThrows
public Exception decode(String methodKey, Response response) {
InputStream inputStream = response.body().asInputStream();
byte[] byteArray = IOUtils.toByteArray(inputStream);
String responseBody = new String(byteArray);
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(responseBody);
String error = jsonNode.get("error") == null ? null : jsonNode.get("error").asText();
String errorDescription =
jsonNode.get("error_description") == null
? null
: jsonNode.get("error_description").asText();
throw new BaseRunTimeException(response.status(), error, errorDescription);
}
}
📙TmdbClientConfig
@Import(TmdbErrorDecoder.class)
public class TmdbClientConfig {
@Bean
@ConditionalOnMissingBean(value = ErrorDecoder.class)
public TmdbErrorDecoder commonFeignErrorDecoder() {
return new TmdbErrorDecoder();
}
@Bean
Encoder formEncoder() {
return new feign.form.FormEncoder();
}
}
📙TmdbClient
@FeignClient(
name = "TmdbClient",
url = "\"http://api.koreafilm.or.kr/openapi-data2/wisenut/search_api/search_json2.jsp?collection=kmdb_new2",
configuration = TmdbClientConfig.class)
public interface TmdbClient {
@GetMapping("&movieId={movieType}&movieSeq={movieId}&detail=Y&ServiceKey={tmdb}")
@Headers({"accept: application/json", "Authorization: Bearer {tmdb}"})
void getMovieData(@Param("movieType") String movieType, @Param("movieId") String movieId, @Param("tmdb") String tmdb);
}
이를 테스트해보기 위해 테스트 코드를 짜보았다
멀티모듈을 사용한 프로젝트이고 Infra 모듈에서 실행한 테스트이므로 이에 맞게 설정을 해줘야한다.
그리고 여러 profile을 사용하고 있기 때문에 local profile설정을 해줘야지 오류가 안나고 Test가 실행이된다
📙InfraIntegrateProfileResolver
public class InfraIntegrateProfileResolver implements ActiveProfilesResolver {
@Override
public String[] resolve(Class<?> testClass) {
// some code to find out your active profiles
return new String[] { "local","infra","core"};
}
}
📙InfraIntegrateTestConfig
@Configuration
@ComponentScan(basePackageClasses = {InfraApplication.class, CoreApplication.class})
public class InfraIntegrateTestConfig {
}
📙TmdbClientTest
@SpringBootTest(classes = InfraIntegrateTestConfig.class)
@AutoConfigureWireMock(port=0)
@ActiveProfiles(resolver = InfraIntegrateProfileResolver.class)
@TestPropertySource(properties = { "spring.thymeleaf.enabled=false","test.port=http://localhost:${wiremock.server.port}"})
public class TmdbClientTest {
@Autowired
private TmdbClient tmdbClient;
@Test
public void testGetMovieData() throws IOException, ParseException {
Path file = ResourceUtils.getFile("classpath:pamyo-response.json").toPath();
// WireMock 설정
stubFor(get(urlEqualTo("/openapi-data2/wisenut/search_api/search_xml2.jsp"))
.withQueryParam("collection", equalTo("kmdb_new2"))
.withQueryParam("movieId", equalTo("K"))
.withQueryParam("movieSeq", equalTo("35655"))
.withQueryParam("detail", equalTo("Y"))
.withQueryParam("ServiceKey", equalTo("33D62G26J6LHL95UV54Y"))
.willReturn(aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.withBody(Files.readAllBytes(file))));
// 테스트할 Feign Client 메소드 호출
try {
String mmovieData = tmdbClient.getMovieData("K", "35655", "Y","a");
System.out.println(mmovieData);
JsonParser jsonParser = new JsonParser();
//3. To Object
//값 처리하는 로직
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(mmovieData);
//4. To JsonObject
JsonNode movieData = rootNode.path("Data").path(0).path("Result").path(0);
String title = movieData.path("title").asText();
title = title.trim();
String directorNm = movieData.path("directors").path("director").path(0).path("directorNm").asText();
String plotText = movieData.path("plots").path("plot").path(0).path("plotText").asText();
String firstPosterUrl = movieData.path("posters").asText().split("\\|")[0];
//System.out.println(tes);
System.out.println(title +directorNm +plotText+ firstPosterUrl);
// 응답이 예상대로 받아졌는지 검증합니다.
assertNotNull("check",tes);
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
여기서 반드시
@SpringBootTest(classes = InfraIntegrateTestConfig.class)
@AutoConfigureWireMock(port=0)
@ActiveProfiles(resolver = InfraIntegrateProfileResolver.class)
@TestPropertySource(properties = { "spring.thymeleaf.enabled=false","test.port=http://localhost:${wiremock.server.port}"})
이 설정 annotation들을 붙여줘야 실행이 된다
특히 FeignClient Test에서는 실제로 우리가 실행하고 있는 서버가 호출을 하고 있는 지 즉, 클라이언트가
http://localhost:${wiremock.server.port}/openapi-data2/wisenut/search_api/search_xml2.jsp
이 URI로 요청을 하는지 확인해야 하기 때문에 RandomPort든 Port를 지정해줘서 Test를 해야한다
이 설정을 해주면 단순히 원 주소, 즉 tmdb의 서버한테 요청이 잘 가고 있는지만 테스트가 되므로
우리의 포트에서 실행이 되고 있는지를 테스트해야 제대로 테스트를 한 것이다
728x90