UserRepository에 대한 테스트 클래스를 만들고 findByEmail() 이라는 메서드에 대한 테스트 코드를 작성했다.
미리 setUp에서 MockUser를 만들고 JPA에서 기본적으로 제공하는 repository.save() 메서드를 이용해 데이터베이스에 저장하고, findByEmail()로 유저를 잘 찾아오는지 assertThat을 이용해 검증한다.
하지만 오류가 발생했다..
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.example.demo.entity.User#1]
오류의 내용을 추려서 검색해보니 StaleObjectStateException으로 , Hibernate에서 Optimistic Locking이 활성화된 상태에서 발생하는 오류라고 나왔다.
"Row was updated or deleted by another transaction"
한 트랜잭션이 데이터베이스에서 특정 행을 조회 후 변경 또는 삭제하려고 할 때, 그 동안 다른 트랜잭션이 같은 행을 업데이트 하거나 삭제기 때문에 충돌이 발생했다는 것이다.
다시 콘솔에 출력된 내용을 보니 친절하게 어디가 문제인지 알려준다.
25번째 줄에는 MockUser를 save하는 코드가 작성되어 있다.
흠.. 뭐가 문제일까 생각하다가 User 클래스를 다시 한번 확인했고,
ID 생성전략이 GenerationType.IDENTITY 라는 걸 확인했다. save 메서드가 호출될 때 자동으로 Id값을 1씩 증가시키면서 데이터베이스에 저장하는데, 테스트 코드에서 MockUser를 만들 때 넣어줬던 임의 Id값이 문제가 될 수도 있겠다고 생각했다.
기존에 있던 코드를 제거하고 Id 값을 뺀 나머지 값만 초기화 시키는 생성자로 MockUser를 만들어주었다.
테스트가 성공적으로 진행된 모습과 함께 쿼리도 기대했던 대로 잘 나오는 모습을 확인 할 수 있었다 !