인프런 커뮤니티 질문&답변

박기현님의 프로필 이미지

작성한 질문수

Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트

테스트 추가하기: h2를 이용한 service 테스트

create test 부분에서 시퀀스 문제가 있습니다.

24.02.18 19:19 작성

·

558

1

단일 테스트는 문제 없지만 전체 테스트 진행 시

테이블의 id의 시퀀스가 계속 증가 하는 문제로
jpa save 시 id 1에 저장하려는 문제가 발생하여

user-service-test-data.sql

-- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
-- values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
-- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
-- values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);


insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
values ('kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
values ('kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);


post-service-test-data.sql


-- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
-- values (1, 'kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
-- insert into `users` (`id`, `email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
-- values (2, 'kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);
-- insert into `posts` (`id`, `content`, `created_at`, `modified_at`, `user_id`)
-- values (1, 'helloworld', 1678530673958, 0, 1);


insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
values ('kok202@naver.com', 'kok202', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'ACTIVE', 0);
insert into `users` (`email`, `nickname`, `address`, `certification_code`, `status`, `last_login_at`)
values ('kok303@naver.com', 'kok303', 'Seoul', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaab', 'PENDING', 0);
insert into `posts` (`content`, `created_at`, `modified_at`, `user_id`)
values ('helloworld', 1678530673958, 0, 1);
delte-all-data.sql

delete from `posts` where 1;
delete from `users` where 1;

ALTER TABLE `users` ALTER COLUMN id RESTART WITH 1;
ALTER TABLE `posts` ALTER COLUMN id RESTART WITH 1;

이와 같이 변경하였는데 혹시 다른 방법이 있을까요?

답변 3

1

하늘님의 프로필 이미지

2024. 05. 30. 10:40

test-application.properties보시면 spring.jpa.hibernate.ddl-auto=create-drop으로 테스트할 때 마다 테이블이 생성되고 지워집니다.

0

pwmetus님의 프로필 이미지

2024. 06. 06. 00:42

동일한 문제로 질문하려 했는데, 선질문이 있네요.(감사)

(혹시 놓친 부분이 있다면 체크해봐야 겠지만)

학습하는 입장에서 그대로 진행하다 발생한 문제로 보여서 당황되는 부분이 있습니다.

 

앞선 질문처럼 보완이 필요한 부분이 있다면 추가 안내가 필요할 듯 합니다.

 

저의 상황은

user-service-test-data.sql 에서 주석상태의 원래쿼리로 하면,

앞서정의한 테스트 메소드 4건은 정상실행됩니다.

이후 create 메서드를 추가하면 (저도)unique 오류가 발생합니다.

이때, user-service-test-data.sql 에서 id 컬럼을 제외한

수정된 쿼리로 테스트를 실행하면, create 테스트는 실행되는데,

(이름은 변경한)getById_Active상태유저조회() 테스트에서

id=1로 조회한 entity가 없다고 오류가 납니다.

(특이사항은 저의경우 create 테스트 실행시 강의에서 발생하는 메일발송 부분 에러가 안나서 한번 더 당황.. 목을 만들어야 하는데... ㅎ 네이버메일로 연결해서 그런가? 암튼.)

 

강의시나리오를 따라가며 문제없이(의도한 문제는 제외) 진행하고 싶은데

unique 오류는 어떻게 진행하면 좋을지 코멘트 주시면 감사하겠습니다.

(저가 놓친 부분이 있을 수 있겠지만, 같은분이 계시니 ...)

 

 

pwmetus님의 프로필 이미지

2024. 06. 06. 12:18

확인1.
- 앞서 insert 쿼리에 id 제거하고 실행시 id=1로 조회한 entity가 없다고 오류난 건의 고찰

  • (이름은 변경한)getById_Active상태유저조회() 테스트 건은
    - user-service-test-data.sql 쿼리 id=1 데이터의 id를 11로 수정하여 조치
    > getById_Active상태유저조회() 조회ID를 11로 조회 : 테스트 성공
    * insert 첫쿼리 id를 11로 변경하니 create 테스트시 id=1로 등록하면서 실행되는것 같습니다.

(다음단계인 메일발송에러는 발생하지 않아서 그냥 따라가봅니다.)

 

이준혁님의 프로필 이미지

2024. 09. 08. 00:32

아마 해결하셨을수도 있지만
test-application.properties 파일에서 데이터 소스에 spring.datasource.url=jdbc:h2:~/mem-data;MODE=MySQL;DB_CLOSE_DELAY=-1; 같이 옵션을 안주신거 같아요 MODE=MySQL에 해당하는 부분이 mysql option을 주는 부분인데 h2-console에서 적용을 안해주면 auto increment가 적용이 안돼서 문제가 발생한것 같습니다.

0

인프런 AI 인턴님의 프로필 이미지

2024. 02. 19. 19:21

안녕하세요, 인프런 AI 인턴입니다.

님의 문제는 테스트를 할 때마다 시퀀스가 초기화되지 않아 테스트 데이터의 ID 값 충돌을 경험하고 계신 것으로 이해합니다. Spring Boot에서 테스트를 진행할 때, 데이터베이스의 ID 시퀀스를 초기화하는 몇 가지 방법이 있습니다. 예를 들어, 테스트용 데이터베이스가 메모리 내 임베디드 데이터베이스인 경우에는 테스트가 종료될 때마다 데이터베이스 상태가 자동으로 초기화되어 문제가 되지 않습니다. 그러나 실제 데이터베이스를 사용하는 경우에는 @DataJpaTest 애노테이션을 사용하여 각각의 테스트가 독립적으로 수행되도록 할 수 있습니다.

만약 @DataJpaTest 애노테이션이 적용된 테스트 클래스에서 테스트가 실행될 때마다 롤백이 이루어져야 한다면, 이는 트랜잭션 관리를 통해 해결할 수 있으며, 기본적으로 테스트는 롤백이 이루어집니다. 다음 문서를 참고하시면 좋을 것 같습니다:
- Spring Boot Reference Documentation v3.1.5 - 테스트 트랜잭션 관리

그리고 각 테스트 진행 후에 테이블의 시퀀스를 초기화하기 위해 SQL 스크립트를 사용하시는 것도 좋은 방법입니다. 첨부하신 delte-all-data.sql 파일에서 시퀀스를 초기화하는 부분이 적절하게 적용되었습니다만, 테스트 환경에 따라서는 이러한 SQL 명령이 지원되지 않을 수도 있습니다.

참고로, @DataJpaTest 애노테이션이 적용될 경우에는 기본적으로 기존의 데이터베이스 연결 대신에 내장 메모리 데이터베이스가 사용됩니다. 해당 애노테이션은 @Entity 클래스를 스캔하고, Spring Data JPA 리포지토리를 구성하며, 클래스패스에서 이용 가능한 임베디드 데이터베이스가 있다면 이를 설정합니다. 만약, 실제 데이터베이스에서 테스트를 수행하길 원하신다면 @AutoConfigureTestDatabase(replace = Replace.NONE) 애노테이션 사용을 고려해볼 수 있습니다. 이에 대해서는 다음 문서에서 더 자세한 정보를 얻으실 수 있습니다:
- Spring Boot Reference Documentation v3.1.5 - Auto-configured Data JPA Tests

다른 방법을 찾으신다면, 마이그레이션 도구(예: Flyway or Liquibase)를 사용하여 테스트 실행 전에 데이터베이스를 초기화하는 것도 가능합니다. 이 방법은 테스트 데이터와 스키마를 동기화하는 데에도 도움이 됩니다.

자세한 설정 방법이나 추가적인 도움이 필요하시면, 문서를 참고하시거나 필요한 내용을 질문으로 남겨주세요.