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에 존재했기 때문이다.