expect
- JPA 를 사용하여 entity 를 변경했을 시 update 가 되야하지만, 테스트 코드에서 동작하지 않음.
situation
-
Repository 를 상속한 곳에서 flush 메소드를 만든 후 호출
-> 반응 없음 (sql log 에 update 가 출력 안됨)
-
EntityManager 를 직접 호출하여 flush 수행
-> No EntityManager with actual transaction available for current thread - cannot reliably process ‘flush’ call
-
PersistenceContext 어노테이션 추가
|
|
-> javax.persistence.TransactionRequiredException: no transaction is in progress
-
Test Method 에 @Transactional 을 추가
-> 정상적으로 업데이트 진행
-
entityManager 의 flush 부분 삭제
-> 정상적으로 업데이트 진행
-
1에서 진행했던 Repository 의 flush 메소드 호출 부분 삭제
-> 정상적으로 업데이트 진행
-
@Transactional 은 컨트롤러 상위든 메소드에든 상관 없이 동작
-
Test 메소드가 끝나면 롤백되는 것을 확인
-
삽질을 하면서 AfterEach 사용했었는데.. (junit5 사용)
-> 어찌보면 당연하겠지만, test 메소드의 라이프 사이클 내에 포함되는 것 같다.
-> 즉, beforeEach - Test - afterEach 순으로 진행되며, afterEach 가 끝나야 롤백이 됨
-
사용하고자 하는 기능에 @Transactional 이 있기 때문에 Test 메소드에는 필요 없다고 생각했는데, 이게 잘못된 것 같음.
-
flush 를 해주지 않아도 update 가 된다는 것은?? (추측)
- 테스트 코드 부분
1 2 3 4 5 6 7
@Test @DisplayName("업데이트 성공") @Transactional internal fun success_update() { val updateReq = UpdateReq() updateService.update(updateReq) }
- 서비스 코드 부분
1 2 3 4 5 6
@Transactional fun updateBoard(req: UpdateReq) { ..... val board = repository.findById(req.id) board.update(req) }
-> 기존에는 테스트 코드 부분에 Transactional 이 없었기 때문에 서비스 코드 부분의 Transactional 이 계속 진행중? 이었으나, 테스트 코드 부분에 Transactional 을 추가함으로써 서로 격리가 되어, 서비스 부분의 Transactional 이 갖고 있는 context 는 더 진행할 것이 없기 때문에 update 가 되고, 서비스 객체 자체를 Test 의 Transactional 에 넘겨서 Test 에서 처리하게 하는 것이 아닌가 싶다. 아니면 롤백을 할 때는 서비스의 Transactional 을 수행해야 할 것 같으니, 순서? 같은 걸 스냅샷 같은 방법으로 남겨서 넘긴다던가??
conclusion
- 추측은 위험하지만, 당장의 지식으로 현 상황(삽질)을 정리하고 팠기에..
- @Transactional 에 대한 정리가 필요하다. (적당히 알았는데, 라이프 사이클이라던가 동작 방식을 확실히 알 필요가 생겼다.)
- 자세히 모르고 사용하는 JPA 가 문제인가 싶기도 하다.
영속성 컨텍스트
에 대한 이해도 필요하다. (문제해결을 위해 읽어봤으나, 당장 훑어봐서는 이해가 잘 안된다.)- 테스트 환경에서 JPA 주의점 을 봤지만 제대로 이해를 못했다.
(내가 처한 것과 살짝 다른 것 같은 느낌도 들고 말이지..) - JPA 변경 감지 오늘의 글을 쓰게 해준 고마운 아티클 (처음에는 잘 모르는 상태에서 save 를 사용해서 update 를 했음…)
- 테스트 환경에서 JPA 주의점 을 봤지만 제대로 이해를 못했다.