JPA 테스트 코드 작성시 UPDATE Query 생성이 안되네?

2024. 5. 28. 18:51·프레임워크/자바 스프링

JUnit5에서 DataJpaTest를 사용한 테스트와 데이터베이스 상호 작용

1. DataJpaTest 어노테이션과 테스트 진행

DataJpaTest 어노테이션은 JUnit5에서 JPA 연결 테스트를 작성하는 데 사용되는 편리한 기능입니다. 이 어노테이션은 다음과 같은 특징을 제공합니다.

  • 자동 트랜잭션 관리: 각 테스트 메서드를 시작하고 종료할 때 자동으로 트랜잭션을 시작하고 롤백합니다.
  • 스프링 부트 테스트 설정: 스프링 부트 테스트 환경을 자동으로 구성하여 JPA 및 기타 관련 빈을 사용할 수 있도록 합니다.
  • 데이터베이스 준비 및 정리: 테스트 전에 테스트 데이터베이스를 준비하고 테스트 후 정리합니다.

DataJpaTest를 사용한 테스트 진행 과정은 다음과 같습니다.

  1. 테스트 클래스 작성: @DataJpaTest 어노테이션을 사용하여 테스트 클래스를 정의합니다.
  2. 필요한 빈 주입: 테스트 클래스의 생성자 또는 테스트 메서드에서 필요한 JPA 리포지토리 및 기타 빈을 주입합니다.
  3. 테스트 메서드 작성: 각 테스트 케이스를 나타내는 @Test 어노테이션이 있는 메서드를 작성합니다.
  4. 테스트 로직 구현: 테스트 메서드 내에서 테스트 로직을 구현합니다. 이 로직에는 데이터베이스 조작, 엔티티 검증, 예외 처리 등이 포함될 수 있습니다.
  5. 테스트 실행: JUnit5 테스트 러너를 사용하여 테스트 클래스를 실행합니다.

2. 객체 Update 테스트 및 SQL UPDATE Query 생성

문제

@DataJpaTest를 사용하여 객체 Update 테스트를 작성했지만, 단순히 repository의 save 메서드를 사용하면 SQL UPDATE Query가 생성되지 않습니다. 이는 @DataJpaTest가 테스트 메서드마다 자동으로 트랜잭션을 시작하고 롤백하기 때문입니다.

해결 방법

SQL UPDATE Query를 생성하고 실제 데이터베이스 변경을 확인하기 위해서는 다음과 같은 방법을 사용할 수 있습니다.


1. @DataJpaTest 제거 및 직접 트랜잭션 관리

@DataJpaTest 어노테이션을 제거하고 테스트 메서드 내에서 직접 트랜잭션을 시작하고 커밋하거나 롤백해야 합니다. @Transactional 어노테이션 또는 EntityManager 메서드를 사용하여 트랜잭션을 관리할 수 있습니다.

@Test
@Transactional // 트랜잭션 시작 및 커밋
void updateArticleTest() {
    // Given
    Article article = articleRepository.findById(1L).orElseThrow();
    String updatedHashtag = "#springboot";
    article.setHashtag(updatedHashtag);

    // When
    articleRepository.save(article); // 엔티티 변경 내용 저장

    // Then
    Article savedArticle = articleRepository.findById(1L).orElseThrow();
    assertThat(savedArticle.getHashtag()).isEqualTo(updatedHashtag);
}

2. @Transactional(propagation = Propagation.NOT_SUPPORTED) 사용

@DataJpaTest 어노테이션을 유지하면서 @Transactional(propagation = Propagation.NOT_SUPPORTED)를 사용할 수 있습니다. 이 어노테이션은 테스트 메서드 내부에서 발생하는 트랜잭션만 영향을 받고, 테스트 범위 외부의 트랜잭션에는 영향을 미치지 않습니다. 즉, 테스트 실행 후 데이터베이스 변경 사항이 유지됩니다.

@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED) // 트랜잭션 롤백 방지
void updateArticleTest() {
    // Given
    Article article = articleRepository.findById(1L).orElseThrow();
    String updatedHashtag = "#springboot";
    article.setHashtag(updatedHashtag);

    // When
    articleRepository.save(article); // 엔티티 변경 내용 저장

    // Then
    Article savedArticle = articleRepository.findById(1L).orElseThrow();
    assertThat(savedArticle.getHashtag()).isEqualTo(updatedHashtag);
}

3. @EntityManager.persist() 사용

앞선 두 가지 방법은 트랜잭션 관리 방식을 변경하는 것이었습니다. 세 번째 방법인 @EntityManager.persist() 는 트랜잭션 관리를 완전히 우회하여 객체를 직접 데이터베이스에 저장하는 방법입니다.

장점

  • 트랜잭션 관리 오버헤드를 줄일 수 있습니다.
  • 테스트 케이스에서 더 세밀하게 데이터 저장 시점을 제어할 수 있습니다.

단점

  • JPA가 제공하는 캐싱 및 변경 감지 기능을 사용하지 않게 됩니다.
  • 직접 트랜잭션을 관리하지 않으면 데이터 무결성 문제가 발생할 수 있습니다.

사용 방법

  1. 테스트 클래스에 @Autowired EntityManager 주입:
    테스트 클래스에서 @Autowired 어노테이션을 사용하여 EntityManager 객체를 주입합니다.
  2. 엔티티 변경:
    테스트 로직에서 수정하고자 하는 엔티티를 가져와 필요한 속성을 변경합니다.
  3. @EntityManager.persist() 호출:
    EntityManager 객체의 persist() 메서드를 사용하여 변경된 엔티티를 데이터베이스에 저장합니다.

예시 코드

@Test
void updateArticleTest(@Autowired EntityManager entityManager) {
    // Given
    Article article = articleRepository.findById(1L).orElseThrow();
    String updatedHashtag = "#springboot";
    article.setHashtag(updatedHashtag);

    // When
    entityManager.persist(article); // 트랜잭션 관리 없이 직접 저장

    // Then (선택적)
    Article savedArticle = articleRepository.findById(1L).orElseThrow();
    assertThat(savedArticle.getHashtag()).isEqualTo(updatedHashtag);
}

주의 사항

@EntityManager.persist() 를 사용할 경우, 테스트 메서드 내에서 직접 데이터 변경을 관리해야 합니다. jména 다음과 같은 사항을 고려해야 합니다.

  • 트랜잭션 관리: 필요한 경우, entityManager.flush() 메서드를 사용하여 변경 내용을 데이터베이스에 반영하고, 테스트 종료 전에 entityManager.clear() 메서드를 사용하여 영속 컨텍스트를 초기화하는 것이 좋습니다.
  • 데이터 무결성: 테스트 데이터 준비 및 정리가 필요할 수 있으며, 테스트 간의 데이터 간섭을 방지하기 위해 주의하여 설계해야 합니다.

결론

하지만 사실 원하는 것은 한 가지입니다. DB에 데이터가 남을 필요도 없습니다. 오히려 원하지 않습니다. 테스트 이후 데이터가 모두 사라지기를 원합니다.
하지만 Update SQL Query는 만들어져 console에서 식별하기 위해서는 save()메서드 대신 saveAndFlus() 메서드를 사용해야 합니다.

저작자표시 (새창열림)

'프레임워크 > 자바 스프링' 카테고리의 다른 글

[spring cloud][ecommerce] 개요 & 구성  (0) 2024.08.12
콘서트 예매 서비스에서 발생할 수 있는 동시성 이슈와 처리  (0) 2024.07.20
JPA 연결 테스트 코드  (0) 2024.05.28
[그냥 보는] application.yaml  (0) 2024.05.28
로깅 출력 어느 것으로?(feat.Interpolation vs Concatenation)  (0) 2024.04.22
'프레임워크/자바 스프링' 카테고리의 다른 글
  • [spring cloud][ecommerce] 개요 & 구성
  • 콘서트 예매 서비스에서 발생할 수 있는 동시성 이슈와 처리
  • JPA 연결 테스트 코드
  • [그냥 보는] application.yaml
hyeseong-dev
hyeseong-dev
안녕하세요. 백엔드 개발자 이혜성입니다.
  • hyeseong-dev
    어제 오늘 그리고 내일
    hyeseong-dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (284)
      • 여러가지 (108)
        • 알고리즘 & 자료구조 (72)
        • 오류 (4)
        • 이것저것 (29)
        • 일기 (2)
      • 프레임워크 (39)
        • 자바 스프링 (39)
        • React Native (0)
      • 프로그래밍 언어 (38)
        • 파이썬 (30)
        • 자바 (3)
        • 스프링부트 (5)
      • 운영체제 (0)
      • DB (17)
        • SQL (0)
        • Redis (17)
      • 클라우드 컴퓨팅 (2)
        • 도커 (2)
        • AWS (0)
      • 스케쥴 (65)
        • 세미나 (0)
        • 수료 (0)
        • 스터디 (24)
        • 시험 (41)
      • 트러블슈팅 (1)
      • 자격증 (0)
        • 정보처리기사 (0)
      • 재태크 (5)
        • 암호화폐 (5)
        • 기타 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    그리디
    celery
    RDS
    WebFlux
    mybatis
    FastAPI
    OOP
    reactor
    Spring WebFlux
    완전탐색
    EC2
    Python
    SAA
    spring
    취업리부트
    Docker-compose
    ecs
    자바
    파이썬
    백준
    항해99
    AWS
    시험
    docker
    Redis
    #개발자포트폴리오 #개발자이력서 #개발자취업 #개발자취준 #코딩테스트 #항해99 #취리코 #취업리부트코스
    java
    DP
    프로그래머스
    Spring Boot
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
hyeseong-dev
JPA 테스트 코드 작성시 UPDATE Query 생성이 안되네?
상단으로

티스토리툴바