@Transactional,@Commit

2022. 3. 30. 12:18BackEnd(Java)/테스트

JPA에서 DB 연산(C,R,U,D)은 Transaction 단위 안에서 실행된다. 즉, 트랜잭션이 없는 연산은 실행될 수가 없다. JPA에서는 @Transactional라는 어노테이션을 제공하여 트랜잭션 기능을 제공한다. 실제 코드를 보면서 이해해 보자!

 

아래의 실제 테스트를 진행 중 그림 1과 같이 오류메시지가 나타났고 확인해 보니 "현재 스레드에 엔티티 매니저가 없다 그래서  persist 함수를 호출할 수가 없다"라는 에러 메시지가 뜬것을 확인할 수 있다.

 

앞에서 언급했듯이 JPA는 Transcation 단위 안에서 실행되므로 @Transactional 어노테이션을 입력해주면 실행이 된다!

 

수정 전 코드

 

그림 1 - 오류 메시지

@Transactional 어노테이션을 추가 후 실행하였다.(그림 2 참고)

 

수정 후 코드
 
그림 2 - 테스트 성공

그런데... 실행은 잘 됐는데 DB에 보니 값이 반영이 안 되었음... (뭐지...?)

로그를 확인해 보니 트랜잭션 RollBack을 하는 문구가 보였고 구글에서 찾아보니 @Transcational 어노테이션은 테스트에서 코드 실행 후 자동으로 Rollback을 한다. 그래서 실제 Commit이 되지 않아 DB에 값이 반영되지 않았던 것이다!

 

 
그림 3 - RollBack 현상

실제로 DB에 값을 반영하기 위해서는 테스트 함수에 @Commit 어노테이션을 사용하면 DB에 Commit이 되어 값이 반영이 된다.(그림 4 참고)

 
그림 4 - @Commit 적용

 

아래의 그림 5를 보면 실제 DB에 값이 반영된 것을 확인할 수 있음

그림 5 - DB 값 반영 확인

 

 

결론

테스트 코드 돌릴 때 DB에 반영하고 싶으면 @Commit 어노테이션을 사용하라! 아니면 JPA가 자동으로 RollBack 시켜 버린다.

 

참고사항

참고로 @SpringBootTest는 스프링, 통합 테스트에 사용하는 어노테이션으로 Repository 안에는 EntityManager을 사용하여 대부분의 연산을 수행하게 된다. EntityManager를 사용하려면 스프링과 통합 테스트가 필요하므로 @SpringBootTest 어노테이션을 사용하였다!

 

실제 개발 테스트도 중요한데, 테스트 코드 짜는 거가 더 중요하다고 느껴진다.. 더 고민을 해봐야겠음..

 

반응형

'BackEnd(Java) > 테스트' 카테고리의 다른 글

JUnit5 Parameterized Tests  (0) 2022.07.09
AssertJ을 사용해보자!  (0) 2022.07.09
[assertJ] isEqualTo vs isSameAs 비교  (0) 2022.03.30
단위 테스트  (0) 2022.03.30