2022년 08월 30일(화)
Programmers 문제 풀기
FIKA Test 환경 설정 및 테스트 추가
알고리즘 스터디
현재 데이터가 들어가 있는 프로젝트에 영향을 주지 않으면서, Test 코드를 설정하기 위해 test용 Property를 구성했다. Spinrg Project에는 main과 test 패키지가 있는데, test path에 resource/application.yml
을 생성하면, Test 동작은 해당 설정을 따라간다.
Test용 DB를 위해 H2를 사용했고, 그래서 main과 다르게 profile 설정을 하였다.
2가지 문제가 발생했다. @SpringBootTest
를 하면, 모든 Bean
정보가 등록되는데, 이때 Amazon S3 설정도 해주어야 하기 때문에 (test)application.yml
만으로는 실행이 되지 않았다. 민감한 정보이다 보니 다로 분리하여 .gitignore
에 추가했고, 이를 include하는 형식으로 진행했다.
Test 코드에선 또 RDS를 건들여야 하는 메서드가 있어서 data
라는 다른 DBConncetion설정을 가진 property를 추가하였고, 동일하게 S3를 위해 이를 include하였다.
그리고 다음과 같은 오류가 발생했다
org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property 'spring.profiles.include' imported from location 'class path resource
원인은
application-data.yml
--include--> application-test.yml
이 문제였다.
application.yml
을 기본으로 동작하는 프로젝트에서, 다른 설정을 위해 @ActiveProfiles("data")
을 통해 profile을 직접 설정해주었더니, include하는 profile을 찾지 못하는 것이었다. 해결은.. application-test의 내용을 data에 직접 추가하고 include를 삭제하니 잘 동작하였다.
WebTest 구성
독립적으로 동작하는 Web API Test를 구성하려고 했다. 그러기 위해선 @SpringBootTest
가 필요했고(JPA를 통한 데이터 저장이나 조작이 필요했음), @BootstrapWith
를 중복으로 포함한 @WebMvcTest
를 선택할 수 없었다. Configuration error: found multiple declarations of @BootstrapWith for test class java.lang.IllegalStateException: Configuration error: found multiple declarations of @BootstrapWith for test class
에러 발생
간편하고 빠른 mockMvc
를 사용하기 어려워졌고, restTemplate을 사용했다. 여기서 문제는, 안드로이드와 통신하기 위해 만들어둔 매우 깊게 심어진 응답 형태였다.
ResponseEntity<ApiResponse<Object>>
이때, xxxForObject(url, {응답받을 객체}.class)
를 사용해야 하는데, 내가원하는 타입으로 매핑이 불가능했다.
런타임 시에는 generic의 타입 정보가 사라져 지정한 객체로 응답하지 않고 Object
클래스로 응답하더라.. 그리고 xxxForObject
는 T에 Object가 넘어가면, LinkedHashMap
으로 매핑해버린다
RestTemplate이 jackson ObjectMapper를 사용하고 있기 때문이다
그럼 어떻게 구성할까 더 찾아보니 다음과 같은 솔루션을 얻었다
ParameterizedTypeReference
을 구성하여 typeToken을 넘겨주는 것이다. 런타임시 Type erasure로 인해 사라지는 타입을 정해주면 된다. Spring에서 제공해주는 ParameterizedTypeReference
를 통해 타입정보를 설정해주는 것이다.
이런 형식(?)은 RestTemplate에서 자주 사용되고, 익명 클래스로 사용한다고 한다. 또, xxxForObject
처럼 class<T>
로 응답을 넘기는 메서드를 사용하지 말고, ParameterizedTypeReference<T>
를 사용할 수 있는 exchange 메서드를 사용하자
FIKA API 연결 시 Kakao login
클라이언트에서 kakao login 완료 후, 발급받은 AccessToken을 서버로 요청한다
서버는 요청 받은 AccessToken으로 카카오에 요청하여 사용자 정보를 받는다. 이때 응답하는 사용자 정보에서 Email을 정규 표현식을 통해 추출하고, 이 이메일로 회원가입을 시키게 했다.
문제는 이메일이 항상 넘어오지 않는 경우가 있었다. 이메일 사용권한이 선택이었기 때문에, 정규표현식으로 추출한 Email을 찾을 수가 없었다. Kakao 비즈를 등록하여 이메일 권한을 필수로 변경하여 수정하였지만, 굉장히 위험한 방식이었던 것 같다. 필수, Unique한 데이터로 가입을 시켰어야 했는데 안일하게 생각했던 것 같다.
/test
에선 또 다른 Profile
을 설정 할 수 있고, 덕분에 여러 데이터베이스 설정할 수 있다. 그리고 독립적인 테스트에 대해선 조금 고민이 필요할 수 있을 것 같다. Contorller(API) 테스트에서 JPA까지 개입하는 게 좋은 지 고민해보자.ddl-auto : create
처럼 비울 수 있는 방법이 있는지 찾아보자