JPA 테스트 코드 작성 시 주의사항

Jiwon Park·2023년 7월 9일

각 테스트는 순서에 영향을 받지 않고 독립성을 유지해야 한다. Junit 테스트코드 작성시 @Transactional을 테스트 클래스에서 사용하면 각 메소드에서 처리된 데이터를 테스트 종료시 롤백시켜주어 자주 사용한다.

@SpringBootTest
@Transactional
class StudyServiceImplTest {

서비스 로직에서 더티체킹으로 데이터를 수정하는 메소드를 작성하였는데 @Transactional을 깜빡하고 빼먹어도 테스트코드의 @Transactional 로 인해 테스트는 정상적으로 통과되었다.
직접 클라이언트에서 요청을 보내고 나서야 제대로 수행이 안되는 걸 확인하였다.

또한 더티체킹으로 수정 시 트랜잭션이 종료될 때 flush가 된다. @Transactional을 사용한 테스트 코드에서는 flush전 롤백이 되므로 update쿼리가 나가지 않아 그 전에 수동으로 flush를 넣어줘야 한다.
조회나 수정 등을 통합 테스트할 경우 테스트 전 insert쿼리로 save할 때 영속성 컨텍스트에 값이 들어가므로 쿼리를 제대로 확인하려면 clear까지 넣어준다.
따라서 더티체킹 수정 시 수정 메소드 호출 전 후로 clear, flush를 해주니 select, update 쿼리가 제대로 나갔다.

이외에도 jpa는 예상과 다르게 쿼리들이 나갈 수 있어 항상 쿼리를 잘 확인하는게 좋은 것 같다.

@Test
@DisplayName("본인이 등록한 스터디의 제목을 수정한다.")
void modifyStudy(){

    Study study = addStudyMethod();

    em.clear();

    StudyModifyRequest modifyRequest = StudyModifyRequest.builder()
                    .title("수정된 제목")
                    .content("코딩스터디입니다.")
                    .userAccount("asdf1234")
                    .build();

    //when
    studyService.modifyStudy(study.getId(), modifyRequest);

    em.flush();

    //then
    Study findStudy = studyRepository.findById(study.getId()).orElseThrow(StudyNotFound::new);

    assertThat(findStudy.getTitle()).isEqualTo("수정된 제목");
    assertThat(findStudy.getContent()).isEqualTo("코딩스터디입니다.");
  }

테스트 결과 더티체킹으로 수정 시 조회 해올 때(지연로딩) 아래 와 같은 경우 getUser().getUserAccount()호출 시 user조회 쿼리가 추가로 나갔다.

@Override
@Transactional
public void modifyStudy(Long studyId, StudyModifyRequest studyModifyRequest) {

    Study findStudy = studyRepository.whenModifyFindById(studyId).orElseThrow(StudyNotFound::new);

    if(!findStudy.getUser().getUserAccount().equals(studyModifyRequest.getUserAccount())){
        throw new UnAuthorized();
    }

    findStudy.changeStudy(studyModifyRequest);
}

@EntityGraph를 사용하여 N+1을 해결하였다.

@EntityGraph(attributePaths = {"user"})
@Query("select s from Study s")
Optional<Study> whenModifyFindById(Long studyId);
profile
안녕하세요

0개의 댓글