Error

LazyInitializationException

kkkkkdddddhhhhh 2023. 8. 12. 15:37

 

 @Test
    @DisplayName("createTodoList(): todoList 컨트롤러을 이용해  글 생성에 성공하기")
    void test1() throws Exception{
        //given
        Member member = memberRepository.findById("testUser").get();
        String url = "/api/todolist";
        String title = "abc";
        String content = "test1";
        final AddTodoListDTO userRequest = new AddTodoListDTO(member,title,content);

        String requestBody = objectMapper.writeValueAsString(userRequest);
        //객체를 JSON으로 직렬화 한다. (Post로 오는 요청은 JSON으로 오기때문에 직렬화 해줘야함.)

        //when
        ResultActions result = mockMvc.perform(post(url)
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestBody));
        //mock을 통해 JSON를 보냄.

        //then
        result.andExpect(status().isCreated());

        List<TodoBoard> todoBoardList = todoBoardRepository.findAll();

        assertThat(todoBoardList.size()).isEqualTo(1);
        assertThat(todoBoardList.get(0).getContent()).isEqualTo(content);
    }

Post요청을 통한 글 작성 기능 테스트중 문제가 발생했다. (member가 제대로 넘어가지않는 모양..)

디버깅을 진행해 원인 파악에 들어갔다..

 

LazyInitializationException

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member writer;

LazyInitializationException

- 지연 로딩이 적용중이고, 게시물 생성을위해  member 객체를 참조해야하는 상황에서  member객체 참조가되야하는데 참조가 되지 않고있다. 

(게시물 작성에는 member객체가 필요하다.)

 

문제는 테스트 코드상에서의 트랙잭션 범위였다. 

- defer-datasource-initialization: true 

기능을 이용해 data.sql에 테스트 데이터를 db에 생성한 후 memberRepository.findById("testUser")를 이용해 testUser를 반환받기로 생각했는데 이 부분에서 당연하게 memberRepository는 JPARepository의 구현체니까 따로 @Transactional을 하지 않아도 commit이 될거라 생각했다.

 

물론 commit이 되긴했지만 @Transactional은 테스트 케이스내에서는 데이터 베이스의 무결성을 위해 commit 후에 rollback이 진행됬고rollback이 진행되어 member변수가 참조되지 않아 LazyInitializationException 이 발생된듯 싶다.

 

해결방안

@Trasactional 을 테스트 메서드단위에 적용시켜 테스트가 종료되고 나서 rollback되도록 적용하니 정상적으로 테스트가 성공했다.