728x90
문제
- 로컬 환경에서 테스트하고 빌드까지 잘 되는 것을 확인했지만, github action을 사용한 build에서 데이터베이스와 연결이 안 된다는 에러가 발생했다.
해결 과정 1. Github Actino에서 MySQL을 사용하기
- Github Action 환경이 어떻게 되어 있는지 간단하게 살펴 보았다.
- 이벤트를 발생시키면 Runner에서 동작하는 원리였는데 얘가 컨테이너 내부에서 작업을 실행한다.
- 해당 컨테이너 환경에 MySQL이 없어서 발생하는 에러였고, MySQL을 사용할 수 있는 설정을 포함해서 해결할 수는 있었다. 하지만 그러면 전체 작업 수행 시간이 늘어나는 문제가 있어서 다른 방법을 고민해 보았다.
- 만약 이 방법을 사용할 것이라면 아래처럼 작업을 추가해 주면 된다
- services: mysql: image: mysql:8.0 env: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: your_database MYSQL_USER: your_user MYSQL_PASSWORD: your_password ports: - 3306:3306
해결 과정 2. 테스트 환경 분리하기
- 테스트 과정에서 DB와의 의존성이 문제니까 테스트에서만 이 의존성을 분리하면 된다고 생각했다.
- 처음엔 H2 DB를 생각했지만, 그럼 실제 내가 사용하는 MySQL과 환경이 완벽하게 일치하지 않기 때문에 언젠간 문제가 발생할 수 있다고 생각했다.
- 그래서 다른 방법을 찾아보았고, testcontainers라는 것을 알게 되었다.
- testcontainers는 테스트할 때 도커 컨테이너 환경을 사용하여 필요한 컨테이너를 띄우고, 테스트가 종료되면 제거한다. 즉, 테스트 시에만 잠깐 필요한 컨테이너를 띄워서 테스트에만 사용할 수 있는 것이다.
- Github actions도 컨테이너 환경에서 동작하니 따로 도커 설치도 필요 없고, 바로 사용할 수 있으며 무엇보다 테스트를 독립적으로 실행하면서 내가 필요한 MySQL을 사용한 테스트를 할 수 있었다.
testImplementation "org.junit.jupiter:junit-jupiter:5.9.3"
testImplementation "org.testcontainers:testcontainers:1.19.4"
testImplementation "org.testcontainers:junit-jupiter:1.19.4"
testImplementation "org.testcontainers:mysql:1.19.4"
- 우선 위와 같이 의존성을 추가해 준다.
- 버전이나 보다 상세한 사용법은 https://testcontainers.com/ 여기에 들어가서 확인하면 된다.
spring:
config:
activate:
on-profile: test
datasource:
url: jdbc:tc:mysql:8.0.33:///
driver-class-name: org.testcontainers.jdbc.ContainerDatabaseDriver
username:
password:
jpa:
hibernate:
ddl-auto: update
- 그리고 테스트 환경에서 사용할 application-test.yml 파일을 생성한다. datasource 부분만 조금 수정해서 사용하면 끝이다. url에 tc가 들어간 부분을 주의해 주고 [ :/// ] 여기까지가 필요한 최소한의 url이다. 뒷부분은 원래 사용하던 시간 설정 등을 넣으면 된다.
사실 여기까지 하니까 테스트 코드는 testcontainers를 사용해서 테스트를 잘 수행했다. 하지만 가장 먼저 수행되는 테스트가 같은 에러로 항상 실패했고, 원인에 대해 고민을 했다.
해결 과정 3. @SpringBootTest 원리 파악하기
- 가장 먼저 수행되는 테스트는 가장 최상단에 있는 테스트 클래스였다.
- 테스트 코드 동작을 위해 있던 의미 없던 테스트 클래스였는데 여기에는 @ActiveProfiles 어노테이션이 없었다. 그래서 발생한 에러였다. 얘는 프로젝트의 applicaiton.yml을 사용하니까 당연히 MySQL이 없어서 발생하는 에러였다.
- 해당 클래스를 제거하니 문제가 없었지만 여기서 내가 잘못 알고 있었던 @SpringBootTest에 대해 알게 되었다.
- 저 애노테이션을 붙이면 @SpringBootApplication을 찾아서 이를 활용해서 빈을 생성할 텐데, 나는 @SpringBootTest가 붙은 것들은 환경을 전부 공유하는 줄 알고 있었다. 사실 각각의 @SpringBootTest마다 분리되어 있고, 이는 각 테스트 환경을 독립적으로 서로 영향을 미치지 않게 해주는 것이었다.
내가 Github Actions의 작업들을 구성하진 않았지만 간단하게나마 어떤 환경에서 어떻게 실행되는지, 그리고 내가 잘못 알고 있던 스프링의 테스트 관련 기능들에 대해 알게 되었다.
사실 @SpringBootTest의 원리는 알고 있어도, 실행이 잘되는지 확인하기 위한 메인 클래스 테스트 코드가 있고, 이를 신경 쓰지 않는다면 삽질을 꽤 오래 할 것 같다.
728x90
'Java > Mini-Pay 프로젝트' 카테고리의 다른 글
코드리뷰 적용, 다시 Redis로.. - MiniPay(5) (1) | 2024.05.21 |
---|---|
ThreadPoolTaskExecutor를 사용한 비동기 처리로 이체 서비스 만들기 - MiniPay(3) (0) | 2024.04.08 |
프로젝트 설계, 이체 시 동시성과 DB Isolation Level 고민 및 적용 - MiniPay(1) (0) | 2024.02.04 |