@Transactional 어노테이션을 테스트 코드에 붙이면 다음과 같은 장점이 있어요!

트랜잭션 전파

한 트랜잭션 A 안에서 또다른 트랜잭션 B가 발생했을 때 A가 B를 이어받아 사용할 수도 있고, A를 일시정지하고 B를 따로 실행하는 등 중첩하는 트랜잭션을 다루는 여러 가지 전략이 있는데 이를 트랜잭션 전파(Transaction Propagation) 전략이라고 부릅니다.

스프링에서 제공하는 @Transactional은 트랜잭션 전파의 기본 전략으로 REQUIRED를 사용해요.

Untitled

REQUIRE 전략은 다음과 같은 특징을 가진 전략입니다.

  1. 외부 트랜잭션이 존재하지 않으면 새로운 트랜잭션을 만들어 사용한다.
  2. 외부 트랜잭션이 존재하면 그 트랜잭션을 이어받아 사용한다.
  3. 내부 트랜잭션과 외부 트랜잭션이 모두 커밋해야 진짜 트랜잭션 커밋을 하고, 하나라도 롤백한다면 전체가 롤백한다.

Untitled

이 이야기가 테스트의 @Transactional이랑 무슨 상관일까요? 테스트 코드에 @Transactional을 붙여주면 위에서 이야기한 트랜잭션 전파로 인해 테스트 코드가 외부 트랜잭션, 서비스 코드가 내부 트랜잭션이 됩니다.

그리고 REQUIRED 옵션으로 인해 테스트 코드와 서비스 코드가 동일한 트랜잭션 하에서 동작하기 때문에, JPA에서 엔티티를 조회할 때 이용하는 영속성 컨텍스트를 테스트 코드 쪽에서도 사용할 수 있다는 큰 장점이 있죠!

Untitled

영속성 컨텍스트의 범위를 확장한 덕분에, 테스트코드에서 엔티티의 필드 값을 검증하고 싶을 때 지연로딩으로 인한 LazyInitializationException 걱정 없이 객체를 탐색하면서 Assertions.assertThat(member.getTeams().get(0).getImage()) 이런 코드를 작성해 사용할 수 있습니다.

무슨 뜻인지 헷갈린다면 그냥 테스트 코드에서 @Transactional을 싹 다 떼보세요! 분명 LazyInitializationException때문에 깨지는 테스트가 몇 개 나올거에요 😃


테스트 데이터 롤백