Tech/Spring

SpringBootTest : @Transactional

봄의 개발자 2023. 12. 15.
728x90
반응형
  • 스프링은 테스트 데이터 초기화를 위해 트랜잭션을 적용하고 롤백하는 방식을 @Transactional 애노테이션 하나로 깔끔하게 해결해준다.

SpringBootTest : @Transactional
@Transactional 추가

 

SpringBootTest : @Transactional
테스트 성공

  • 다시 테스트를 실행해도 실패되지 않고 모두 성공한다 마치 롤백되는 것처럼!!

 

@Transactional 원리

  • 스프링이 제공하는 @Transactional 애노테이션은 로직이 성공적으로 수행되면 커밋되도록 동작한다.
  • 그런데 @Transactioanl 애노테이션을 테스트에서 사용하면 아주 특별하게 동작한다.
  • 테스트에서는 스프링은 테스트를 트랜잭션 안에서 실행하고, 테스트가 끝나면 트랜잭션을 자동으로 롤백시켜 버린다.

 

  • @Transactional이 적용된 테스트 동작 방식
  1. 테스트에 @Transactional 애노테이션이 테스트 메서드나 클래스에 있으면 먼저 트랜잭션을 시작한다.
  2. 테스트를 로직을 실행한다. 테스트가 끝날 때까지 모든 로직은 트랜잭션 안에서 수행된다.
    1. 트랜잭션은 기본적으로 전파되기 때문에 레포지토리에서 사용하는 JdbcTemplate도 같은 트랜잭션을 사용한다.
    • 트랜잭션 전파?
  3. 테스트 실행 중에 Insert sql을 사용해서 데이터베이스에 값을 저장한다.
    1. 물론 테스트가 레포지토리를 호출하고, 레포지토리는 JdbcTemplate를 사용해서 데이터 저장
  4. 검증을 위해서 Select sql로 데이터를 조회한다. 여기서 앞서 저장한 데이터가 조회된다.
    1. Select sql도 같은 트랜잭션을 사용하기 때문에 저장한 데이터를 조회할 수 있다. 다른 트랜잭션에서는 해당 데이터를 확인할 수 없다.
    2. 여기서 assertThat()으로 검증이 모두 끝난다.
  5. @Transactional이 테스트에 있으면 테스트가 끝날 때 트랜잭션을 강제로 롤백한다.
  6. 롤백에 의해 앞서 데이터베이스에 저장한 데이터들이 제거된다.

 

참고
- 테스트 케이스의 메서드나 클래스에 @Transactional 을 직접 붙여서 사용할 때 만 이렇게 동작한다. 그리고 트랜잭션을 테스트에서 시작하기 때문에 서비스, 리포지토리에 있는 @Transactional 도 테스트에서 시작한 트랜잭션에 참여한다. (참여한다는 것은 기존 트랜잭션이 따라서 이어진다는 말과 동일)
- 테스트에서 트랜잭션을 실행하면 테스트 실행이 종료될 때 까지 테스트가 실행하는 모든 코드가 같은 트랜잭션 범위에 들어간다고 이해하면 된다. 같은 범위라는 뜻은 쉽게 이야기해서 같은 트랜잭션을 사용한다는 뜻이다. 그리고 같은 트랜잭션을 사용한다는 것은 같은 커넥션을 사용한다는 뜻이기도 하다.

 

 

결론

  • 테스트가 끝난 후 개발자가 직접 데이터를 삭제하지 않아도 되는 편리함을 제공한다.
  • 테스트 실행 중에 데이터를 등록하고 중간에 테스트가 강제로 종료되어도 걱정이 없다. 이 경우 트랜잭션을 커밋하지 않기 때문에, 데이터는 자동으로 롤백된다.
  • 트랜잭션 범위 안에서 테스트를 진행하기 때문에 동시에 다른 테스트가 진행되어도 서로 영향을 주지 않는 장점이 있다

 

 


강제로 커밋하기 - @Commit

@Commit 을 클래스 또는 메서드에 붙이면 테스트 종료후 롤백 대신 커밋이 호출된다. 참고로 @Rollback(value = false)를 사용해도 된다.

SpringBootTest : @Transactional - undefined - 모든 영역
둘 중 하나만 사용하기

 

SpringBootTest : @Transactional - undefined - 모든 영역
테스트 성공

728x90
반응형

댓글