-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/Test Container #364
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/Test Container #364
Conversation
# Conflicts: # src/main/kotlin/com/wafflestudio/csereal/core/main/api/v2/MainController.kt # src/main/kotlin/com/wafflestudio/csereal/core/main/service/MainService.kt
src/test/kotlin/com/wafflestudio/csereal/global/config/TestMySQLcontainersConfig.kt
Outdated
Show resolved
Hide resolved
이 부분은 SpringTestLifeCycle 설정을 통해서 해결될 수 있는 것으로 알고 있습니다..! (확실하진 않음) (다른 서비스 레이어 테스트 코드 참고해주세요..!) |
@SpringBootTest | ||
@ActiveProfiles("test") | ||
@ContextConfiguration(initializers = [TestContainerInitializer::class]) | ||
@TestInstance(TestInstance.Lifecycle.PER_CLASS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestInstance 어노테이션은 JUnit꺼라 lifecycle이 제대로 적용될지 모르겠네요
추가로 테스트 격리성에 문제가 있으면 kotest 공식 문서랑 아래 블로그 글들 참고해보시면 좋을거 같아요
https://kth990303.tistory.com/374
https://velog.io/@glencode/Kotest%EC%9D%98-Lifecycle-Hook-IsolationMode
testcontainer와 호환이 잘 되는지는 아마 테스트 해봐야할것 같구요
Transactional 어노테이션과 extensions(SpringTestExtension(SpringTestLifecycleMode.Root))를 사용해 문제를 해결하려 했으나, 생성한 엔티티가 아예 조회가 안되는 문제가 생겼습니다 이 문제를 해결하려면 테스트에 트랜잭션을 쓰지 말고, 대신 afterContainer를 이용해 테스트가 끝나고 데이터베이스를 초기화해줘야 한다 생각했습니다. |
return camelCase.replace(Regex("([a-z])([A-Z])"), "$1_$2") | ||
.lowercase(Locale.getDefault()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(사실 저희 케이스 정도는 만족해서 마이너 코멘트입니다.)
엣지케이스가 있는 구현인거 같아요.
- https://www.baeldung.com/java-camel-snake-case-conversion 에 나온 방법으로 보완하던가
- https://github.com/google/guava/wiki/StringsExplained#caseformat 라이브러리 사용이 필요해 보입니다.
(엣지케이스 커버하려면 라이브러리가 나을거 같긴 한데 두 방법 다 괜찮아 보여요)
테스트 코드 봤을 때는 내부에서 별도의 transaction을 생성하는 코드는 없는 것으로 보이는데, 어느 부분에서 다른 transaction이 생성된다는 것일까요? |
트랜잭션이 새로 생기면 조회가 안 되는 게 설명이 되어서 그렇게 생각했는데, 제가 잘못 생각한 것 같습니다 |
ServiceConnection 어노테이션을 사용하면 Spring이 자동으로 TestContainer로 띄워진 컨테이너에 연결이 된다고 합니다
앞으로 모든 테스트 클래스마다 위 어노테이션을 사용해야 합니다 TODO : reservationService에 동시성 문제가 조금 있는 것 같아 일단 테스트에 주석 처리해뒀습니다 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getLoginUser()에서 동시에 유저 생성할때 이슈가 되어서 해당 함수에서는 test user를 찾도록 하고 각 테스트 내에서 loginUser가 필요한 경우 beforeSpec에서 유저를 미리 생성해서 테스트 진행하도록 리팩토링하였습니다. 필요하시면 [1c70642] 확인하시면 됩니다.
Test Container 추가
한줄 요약
테스트 컨테이너 적용했습니다
상세 설명
testcontainer는 테스트 실행시 컨테이너를 도커로 자동으로 띄워줘 사용할 수 있게 하는 라이브러리입니다
외부 의존성 없이 실제 prod과 유사한 환경에서 테스트 진행이 가능합니다
TestContainerInitializer를 사용해서 테스트가 실행 될 때 환경변수를 바꿔주었습니다@ContextConfiguration(initializers = [TestContainerInitializer::class])어노테이션을 적어준다면 MySQL을 이용해 테스트가 진행됩니다
ServiceConnection 어노테이션을 사용하면 Spring이 자동으로 TestContainer로 띄워진 컨테이너에 연결이 된다고 합니다
앞으로 모든 테스트 클래스마다 위 어노테이션을 사용해야 합니다
[
9d3e478
]: 테스트 환경에서 getLoginUser()가 2번 이상 실행되면 데이터베이스에 같은 이름의 사람을 2번 이상 저장하게 되어 Unique 때문에 오류가 발생해서 고쳤습니다.TODO
테스트컨테이너 인스턴스를 하나 만들어서 공유하는 방식이라 한 테스트에서 사용했던 데이터가 남아있다는 문제가 있습니다.예를 들어서, 공지를 추가하고 공지가 1개 있음을 확인하는 테스트가 2개 있다고 해보겠습니다. 현재는 테스트 하나가 끝나도 데이터베이스에는 데이터가 계속 남아있어 다음 테스트에는 공지가 1개 더 추가되어 2개가 생겨버립니다.
이렇게 테스트 코드끼리 서로 간섭할 수 있는 부분을 해결해야 합니다.
reservationService에 동시성 문제가 조금 있는 것 같아 일단 테스트에 주석 처리해뒀습니다