티스토리 뷰
[Test] JPA DataIntegrityViolationException 발생 테스트 복구
ryumodern 2021. 11. 19. 18:56테스트를 돌리는 방법에는 아래 사진과 같이 테스트 폴더 자체를 선택해 Run을 눌러 돌리는 방법이 있고
명령어를 통해 전체 테스트를 돌리는 방법이 있다
단일 모듈 구조라면 테스트 폴더로만 돌리는 게 쉽고 빠르다
멀티 모듈 프로젝트의 경우에도 폴더를 이용해 돌려도 되지만
명령어를 통해 돌리면 빌드 수행 후 전체 테스트 코드가 한방에 돌아가기 때문에 편의성 측면에서 더 낫다
특히나 --parallel 옵션을 줘서 병렬로 수행할 수 있게 만들 수 있다
./gradlew test --parallel
org.springframework.dao.DataIntegrityViolationException
테스트 코드 작성 중 만난 오늘의 에러다
소스 관리를 위해 Github Actions를 써서 빌드&테스트 수행 후 올리고 있는데
풀 리퀘 CI 과정에서 테스트가 자꾸 깨져서 똥줄 탔다
이전까지는 잘 돌아가다가 작성한 테스트 코드를 포함하여 돌리니 터지지 않던 곳까지 터져 살짝 멘붕이 올뻔 했다
위 Exception을 키워드로 찾아보니 아래와 같이 정리할 수 있었다
DataIntegrityViolationException은 더 낮은 레벨의 예외들을 추상화시켜놓은 것이다
값이 잘못되거나 primary key가 잘못 들어가거나 등의 문제로 발생할 수 있다
- ConstraintViolationException
- PropertyValueException
- DataException
문제 상황을 설명해보자면 Service 계층에서의 @SpringBootTest 였고
findById 메서드를 통해 Entity를 찾는 중 에러가 발생했다
이전까지는 문제가 없었으므로 오늘 작성한 코드와 뭔가 겹쳤기 때문에 에러가 발생했음을 알 수 있었고
문제의 소지가 될만한 부분을 살펴봐도 특별할 건 없었기에
살짝씩 고쳐서 재도전을 해봤는데도 계속해서 같은 예외가 발생했다
./gradlew test로 테스트를 돌리는 경우엔 실패하더라도 자세한 로그가 찍히지 않기에 왜 실패했는지
자세한 로그를 보기 위해 service 모듈의 테스트를 폴더째로 돌려봤더니 상세한 설명이 나왔다
프로젝트에서 member_id는 primary key로써 회원의 고유번호를 나타내는 필드다
unique 한 값이 지켜지지 않아 예외가 발생한 것이었고 후처리를 담당할 기능을 추가했다
사실 이전에는 테스트 클래스의 @Transactional을 붙여줬기에 알아서 Rollback이 되고 독립성이 지켜지는 줄 알았는데
test --parallel로 돌렸기 때문에 테스트들이 병렬적으로 수행되고 이미 지운 member_id로 엔티티를 찾거나
같은 member_id로 값을 넣거나 하는 중에 발생한 예외로 생각된다
테스트를 병렬로 돌리지 않거나 규모가 작은 경우에는 후처리까지 해줄 필요는 없지만 작성 시간이 오래 걸리지 않고
수행 시간에 큰 영향을 미치지 않으니 @AfterEach로 전체 삭제, sequence 값 초기화 등의 후처리를 해주도록 하자
'Spring > Spring Framework' 카테고리의 다른 글
[Log4j2] CVE-2021-44228 대응 (0) | 2021.12.13 |
---|---|
[Test] 기묘한 병렬 테스트 (0) | 2021.12.06 |
[MapStruct] DTO 안의 DTO (0) | 2021.10.07 |
[Test] 깨지는 테스트 어떻게 복구할까? (3) | 2021.09.24 |
[MapStruct] MapStruct의 update 기능 사용 주의 (0) | 2021.09.20 |