해결된 질문
작성
·
54
0
69강 테스트 격리에서 테스트가 랜덤으로 실패하는 이유가 뭔가요?
싱글톤때문에 발생하는 문제인건 알겠는데 조회할 때 Exception이 생기는 이유를 모르겠습니다. ㅠㅠ
답변 2
1
안녕하세요. 강의 수강해주셔서 고맙습니다.
69번 수업이면 많이 진행하셨네요. 꼭 끝까지 완료하세요. :)
해당 수업에서 실패하는 테스트가 달라지는 정확한 이유는 저도 모르겠습니다. 그래서 프로그래밍이 어렵다고 말씀드린 것인데요.
분명한 것은 README.md 파일 내용에 따라서 JUnit이 테스트를 실행하는 순서가 달라진다는 점입니다. 그래서 서로 맥락을 공유하는 테스트 중 먼저 실행되는 테스트는 성공하고 나중에 실행되는 테스트는 실패하는데, 이 순서가 테스트와 무관한 파일의 내용에 영향을 받다 보니 우리 입장에서는 말씀하신 것처럼 '랜덤으로' 실패하는 것처럼 느껴지는 것입니다.
혹시 설명이 부족하다면 말씀해주세요!
0
안녕하세요, 인프런 AI 인턴입니다. 3831568님.
테스트가 랜덤하게 실패하는 상황은 주로 테스트 간의 격리가 제대로 이루어지지 않을 때 발생할 수 있습니다. 특히 Java의 Spring Framework에서는 각 테스트가 독립적으로 실행되어야 하며, 동일한 상태나 컨텍스트를 공유하지 않도록 주의해야 합니다. 아래에 가능한 원인과 해결 방법에 대해 설명드리겠습니다.
상태 공유: 싱글톤 빈이나 공유된 리소스가 여러 테스트에서 동일하게 사용될 때 문제가 발생할 수 있습니다. 이러한 싱글톤 객체는 인스턴스 변수에 상태를 저장할 수 있으므로, 하나의 테스트 케이스에서 변경된 상태가 다른 테스트 케이스에 영향을 미칠 수 있습니다.
컨텍스트 재사용: Spring Framework에서는 테스트 간에 애플리케이션 컨텍스트를 재사용합니다. 특별히 컨텍스트를 초기화했거나, 깨끗하지 않은 상태가 남아 있을 경우, 다른 테스트에 영향을 미칠 수 있습니다.
데이터베이스 상태: 테스트 중 데이터베이스에 대한 변경 사항이 롤백되지 않거나 지속되면, 이후 테스트가 예상과 다른 결과를 얻을 수 있습니다. 테스트 데이터가 정확히 초기화되지 않았을 때 발생합니다.
테스트 메서드 간 상태 분리: 각 테스트 메서드에서 사용되는 객체는 반드시 초기 상태를 가져야 합니다. @Test 메서드마다 객체나 서비스를 새로 생성하여 상태를 분리하는 것이 중요합니다.
@DirtiesContext 사용: 특정 테스트 메서드가 컨텍스트를 더럽혔다고 판단되면, 해당 테스트를 마친 후 컨텍스트를 재생성하도록 @DirtiesContext를 사용할 수 있습니다.
데이터 초기화: 각 테스트는 독립적으로 데이터베이스를 정리하거나 필요한 데이터를 삽입하여 시작해야 합니다. Spring의 @Transactional 어노테이션을 사용하여 테스트 후 데이터베이스를 롤백하도록 구현할 수 있습니다.
이와 관련하여 더 이해하고 싶으시다면, “프로젝트 규모가 큰 경우 @SpringBootTest 실행 속도 문제”에서 테스트의 격리와 성능에 대한 추가 토론을 참고하실 수 있습니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
답변 감사합니다. 그래도 제가 조금 더 확인을 해봤는데요
- POST /seller/products
- GET /seller/me
- GET /shopper/me
이렇게 세 개를 동시에 실행할 때 문제가 생기더라구요
저는 200번이랑 500번 에러가 랜덤으로 발생했는데요
testFixture를 사용할 때 Interceptor에 인증정보가 들어있어서 authenticated는 통과되는데
shopper 테스트를 진행할 때 interceptor에 있는 인증정보가 seller이거나 그 반대일 때는 findById에서 데이터를 찾을 수 없어서 500번이 뜨고,
interceptor에 있는 인증정보와 테스트의 엔티티가 같을 때는 200번이 뜨는 것 같아요
그래서 각 테스트마다 interceptor를 초기화하는 방식을 생각해봤습니다.
이것을 POST /seller/products 에 추가하고 재실행하니까 에러없이 완료되더라구요
이렇게 해도 되는걸까요?