SpringBoot 예외테스트와 @Rollback

pickylemon·2024년 7월 9일

Exception 모음

목록 보기
29/31

상황

  • 테이블에 memberId를 Unique키 제약조건을 걸어둔 상태에서,
    memberId가 중복으로 insert되지 않는 것을 확인하는 테스트를 진행중이었다.
//Member Entity
@Entity
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Setter
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int memberSeq;
    @Column(unique = true) //memberId에 유니크 제약 조건 설정
    private String memberId;
    private String passwd;
    private String memberNm;
    private String email;
    @Column(nullable = false)
//    @ColumnDefault("'N'")
    private String authYn = "N";
    private LocalDateTime pwdChngDtm;
    @Column(nullable = false)
//    @ColumnDefault("'now()'")
    private LocalDateTime joinDtm = LocalDateTime.now();

    public Member(String memberId, String passwd, String memberNm, String email){
        this.memberId = memberId;
        this.passwd = passwd;
        this.memberNm = memberNm;
        this.email = email;
    }
}

//테스트 코드

    @Test
    @DisplayName("ID unique키 테스트")
    void memberTest4() {
        //given
        Member member = new Member("memberD", "abcd", "단호박", "abc@abc.com");
        Member member2 = new Member("memberD", "abcd", "찐빵", "abc@abc.com");
        memberJpaRepository.save(member);

        //when, then
        assertThatThrownBy(() -> memberJpaRepository.save(member2))
                .isInstanceOf(DataIntegrityViolationException.class);
    }
  • 하지만 예상과 달리 테스트는 통과하지 못했고
    아래와 같은 에러가 발생했다.
org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:804) ~[spring-tx-6.1.10.jar:6.1.10]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:758) ~[spring-tx-6.1.10.jar:6.1.10]

원인 및 해결

  • 현재 테스트는 @Transactional 어노테이션을 붙여서
    개별 테스트가 끝나면 자동 롤백되게 설정해두었지만,
    DB를 직접 눈으로 확인하기 위해 @Rollback(false)로 자동 롤백을 꺼둔 상태였다.
@SpringBootTest
@Transactional
@Rollback(false)
@Slf4j
class MemberJpaRepositoryTest {
    @Autowired
    MemberJpaRepository memberJpaRepository;
    @Autowired
    EntityManager em;
    
    ...
}
  • assertThatThrownBy로 예외가 잡히면 롤백이 되어야 하는데,
    클래스에 붙인 @Rollback(false)와 충돌이 발생하는 것 같다.
    그래서 UnexpectedRollbackException이 발생해서 테스트가 실패하는 듯...?
  • 해당 테스트에 @Rollback(true)를 추가했더니 테스트가 정상적으로 통과했다.
    @Test
    @DisplayName("ID unique키 테스트")
    @Rollback(true)
    void memberTest4() {
        //given
        Member member = new Member("memberD", "abcd", "단호박", "abc@abc.com");
        Member member2 = new Member("memberD", "abcd", "찐빵", "abc@abc.com");
        memberJpaRepository.save(member);

        //when, then
        assertThatThrownBy(() -> memberJpaRepository.save(member2))
                .isInstanceOf(DataIntegrityViolationException.class);
    }
profile
안녕하세요

0개의 댓글