상황
- 테이블에 memberId를 Unique키 제약조건을 걸어둔 상태에서,
memberId가 중복으로 insert되지 않는 것을 확인하는 테스트를 진행중이었다.
@Entity
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Setter
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int memberSeq;
@Column(unique = true)
private String memberId;
private String passwd;
private String memberNm;
private String email;
@Column(nullable = false)
private String authYn = "N";
private LocalDateTime pwdChngDtm;
@Column(nullable = false)
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() {
Member member = new Member("memberD", "abcd", "단호박", "abc@abc.com");
Member member2 = new Member("memberD", "abcd", "찐빵", "abc@abc.com");
memberJpaRepository.save(member);
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);
}