Inflearn brand logo image

인프런 커뮤니티 질문&답변

3831568님의 프로필 이미지
3831568

작성한 질문수

Spring Boot TDD - 입문부터 실전까지 정확하게

테스트 격리에서 테스트 랜덤 실패 이유

해결된 질문

작성

·

54

0

69강 테스트 격리에서 테스트가 랜덤으로 실패하는 이유가 뭔가요?
싱글톤때문에 발생하는 문제인건 알겠는데 조회할 때 Exception이 생기는 이유를 모르겠습니다. ㅠㅠ

답변 2

1

이규원님의 프로필 이미지
이규원
지식공유자

안녕하세요. 강의 수강해주셔서 고맙습니다.

69번 수업이면 많이 진행하셨네요. 꼭 끝까지 완료하세요. :)

 

해당 수업에서 실패하는 테스트가 달라지는 정확한 이유는 저도 모르겠습니다. 그래서 프로그래밍이 어렵다고 말씀드린 것인데요.

분명한 것은 README.md 파일 내용에 따라서 JUnit이 테스트를 실행하는 순서가 달라진다는 점입니다. 그래서 서로 맥락을 공유하는 테스트 중 먼저 실행되는 테스트는 성공하고 나중에 실행되는 테스트는 실패하는데, 이 순서가 테스트와 무관한 파일의 내용에 영향을 받다 보니 우리 입장에서는 말씀하신 것처럼 '랜덤으로' 실패하는 것처럼 느껴지는 것입니다.

 

혹시 설명이 부족하다면 말씀해주세요!

3831568님의 프로필 이미지
3831568
질문자

답변 감사합니다. 그래도 제가 조금 더 확인을 해봤는데요

- POST /seller/products
- GET /seller/me
- GET /shopper/me

이렇게 세 개를 동시에 실행할 때 문제가 생기더라구요

저는 200번이랑 500번 에러가 랜덤으로 발생했는데요


testFixture를 사용할 때 Interceptor에 인증정보가 들어있어서 authenticated는 통과되는데
shopper 테스트를 진행할 때 interceptor에 있는 인증정보가 seller이거나 그 반대일 때는 findById에서 데이터를 찾을 수 없어서 500번이 뜨고,
interceptor에 있는 인증정보와 테스트의 엔티티가 같을 때는 200번이 뜨는 것 같아요

그래서 각 테스트마다 interceptor를 초기화하는 방식을 생각해봤습니다.

@AfterEach
void tearDown(@Autowired TestFixture fixture) {
    fixture.client().getRestTemplate().getInterceptors().clear();
}

 

이것을 POST /seller/products 에 추가하고 재실행하니까 에러없이 완료되더라구요

이렇게 해도 되는걸까요?

3831568님의 프로필 이미지
3831568
질문자

생각해보니 이 방식으로 하면 모든 테스트마다 interceptor 초기화 코드를 추가 해야해서 번거로울 수 있을 것 같네요

이규원님의 프로필 이미지
이규원
지식공유자

문제를 해결하는 방법은 여러가지가 있을 수 있고 각 상황에 따라서 가장 적합한 방법을 선택하면 된다고 생각합니다. :)

0

안녕하세요, 인프런 AI 인턴입니다. 3831568님.

테스트가 랜덤하게 실패하는 상황은 주로 테스트 간의 격리가 제대로 이루어지지 않을 때 발생할 수 있습니다. 특히 Java의 Spring Framework에서는 각 테스트가 독립적으로 실행되어야 하며, 동일한 상태나 컨텍스트를 공유하지 않도록 주의해야 합니다. 아래에 가능한 원인과 해결 방법에 대해 설명드리겠습니다.

테스트 격리 문제의 원인:

  1. 상태 공유: 싱글톤 빈이나 공유된 리소스가 여러 테스트에서 동일하게 사용될 때 문제가 발생할 수 있습니다. 이러한 싱글톤 객체는 인스턴스 변수에 상태를 저장할 수 있으므로, 하나의 테스트 케이스에서 변경된 상태가 다른 테스트 케이스에 영향을 미칠 수 있습니다.

  2. 컨텍스트 재사용: Spring Framework에서는 테스트 간에 애플리케이션 컨텍스트를 재사용합니다. 특별히 컨텍스트를 초기화했거나, 깨끗하지 않은 상태가 남아 있을 경우, 다른 테스트에 영향을 미칠 수 있습니다.

  3. 데이터베이스 상태: 테스트 중 데이터베이스에 대한 변경 사항이 롤백되지 않거나 지속되면, 이후 테스트가 예상과 다른 결과를 얻을 수 있습니다. 테스트 데이터가 정확히 초기화되지 않았을 때 발생합니다.

해결 방안:

  • 테스트 메서드 간 상태 분리: 각 테스트 메서드에서 사용되는 객체는 반드시 초기 상태를 가져야 합니다. @Test 메서드마다 객체나 서비스를 새로 생성하여 상태를 분리하는 것이 중요합니다.

  • @DirtiesContext 사용: 특정 테스트 메서드가 컨텍스트를 더럽혔다고 판단되면, 해당 테스트를 마친 후 컨텍스트를 재생성하도록 @DirtiesContext를 사용할 수 있습니다.

  • 데이터 초기화: 각 테스트는 독립적으로 데이터베이스를 정리하거나 필요한 데이터를 삽입하여 시작해야 합니다. Spring의 @Transactional 어노테이션을 사용하여 테스트 후 데이터베이스를 롤백하도록 구현할 수 있습니다.

이와 관련하여 더 이해하고 싶으시다면, “프로젝트 규모가 큰 경우 @SpringBootTest 실행 속도 문제”에서 테스트의 격리와 성능에 대한 추가 토론을 참고하실 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

3831568님의 프로필 이미지
3831568

작성한 질문수

질문하기