Repository테스트 Referential integrity constraint violation 오류

선종우·2023년 6월 8일
1

오답노트

목록 보기
1/5

1. 오류상황

  • 게시판 서비스 Repository에 대한 슬라이스 테스트코드 작성 중 Referential integrity constraint violation(SQL Error: 23506, SQLState: 23506) 발생하였다. 외래키 관련 문제인 듯 한데 실 운용 DB에서 테스트 했을 땐 문제가 없었는데, H2 DB로 변경하고 나서 문제가 발생했다.
2023-06-08 20:00:53.435  WARN 21688 --- [    Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 23506, SQLState: 23506
2023-06-08 20:00:53.436 ERROR 21688 --- [    Test worker] o.h.engine.jdbc.spi.SqlExceptionHelper   : Referential integrity constraint violation: "FK6L9VKFD5IXW8O8KPH5RJ1K7GU: PUBLIC.ARTICLE FOREIGN KEY(MEMBER_ID) REFERENCES PUBLIC.MEMBER(MEMBER_ID) (CAST(1 AS BIGINT))"; SQL statement:
insert into article (article_id, created_at, last_modified_at, created_by, modified_by, content, member_id, title) values (default, ?, ?, ?, ?, ?, ?, ?) [23506-214]
  • article table이 member table을 의존하고 있어 외래키를 가지고 있는 구조이다. 그래서 테스트 코드에서는 아래와 같이 Member를 생성하고 Article에 주입해 주었었다.
    {
        defaultMember = Member.builder()
                .id(1L)
                .email("sls@naver.com")
                .password("123456789")
                .build();

        defaultPageRequest = new PageRequest(0, 100);
    }

    public void saveArticles(){
        for(int i = 0; i < 10; i++){
            String title = "제목 " + i;
            String content = "내용 " + i;

            Article article = Article.builder()
                                    .title(title)
                                    .content(content)
                                    .member(defaultMember)
                                    .build();
            articleRepository.save(article);
        }
    }
  • Entity를 생성하였다고 하더라도 Member를 영속화하지 않았기 때문에 DB에는 데이터가 저장되지 않았기 때문으로 추정되었다.

2. 해결방안

  • ArticleRepository에 대한 슬라이스 테스트이기 때문에 MemberRepository를 호출하고 싶진 않았다. 그렇다면 테스트 시점에서 DB에 직접 값을 넣어주면 문제를 해결할 수 있다.
  • 먼저 초기화를 위해 data.sql script를 작성한다.

  • 테스트 설정 파일에 초기화 sql 실행을 위한 설정을 넣어준다.
spring.jpa.defer-datasource-initialization=true 
spring.sql.init.data-locations=classpath:data.sql
  • 예상했던 대로 DB에 참조할 회원 정보가 있으니 테스트가 정상적으로 수행됐다.

  • 실 운용 DB에서는 성공했던 건 해당 ID값에 해당하는 멤버가 이미 Table에 존재했기 때문이다.

0개의 댓글