테스트 코드 작성은 개발 과정에서 아주 중요한 부분이라고 할 수 있다. 하지만 처음 테스트 코드를 작성하는 과정에서는 테스트 방법과 다양한 종류에 대한 이해가 필요하다. 나는 그 부분에 대해 이해가 부족했고, Controller를 시작으로 단위테스트를 작성하려고 했으나, 데이터베이스 연동까지 고려하다 보니 결국 통합테스트를 진행하고 있었다. 통합테스트는 테스트용 데이터베이스를 만들어 빈 데이터베이스에서 테스트를 진행했다.
❓ 문제 상황
각 테스트 메소드를 개별적으로 실행할 때는 성공했지만, 모든 테스트를 한 번에 실행할 때 실패로 뜨는 현상 발생

1. @Transactional 어노테이션을 사용하더라도 테스트 중에 사용한 데이터가 실제 데이터베이스에 저장되기 때문에 이로 인해 각 테스트 간의 의존성 문제가 발생하였고, 특히 데이터베이스에서 사용하는 id 값이 설정해 둔 값과 일치하지 않아 실패함.

2. 로그인 한 유저를 확인할 값(userDetails)으로 MySQL에서 USER 테이블에 저장해 두고 그 값을 setUp해서 사용함.
Long id = 1L;
String email = "1test@test.com";
String encodedPassword = new BCryptPasswordEncoder().encode("qwe123!@#");
String nickname = "1test";
Set<SimpleGrantedAuthority> authorities = Set.of(new SimpleGrantedAuthority("ROLE_USER"));
userDetails = UserDetailsImpl.builder()
.id(user.getId())
.email(email)
.password(encodedPassword)
.nickname(nickname)
.authorities(authorities)
.build();
3. 결국 다른 테이블에서도 id값을 가져와야 하는 상황이 발생. 이것 또한 DB에 값을 저장해 두고 사용한다면 빈 데이터베이스를 만들어서 연결한 의미가 없다는 생각이 들었음.

💡 해결 방법
@BeforeEach 어노테이션을 사용하여 먼저 respository.save(user) 하고, 그 user의 id를 활용하여 userDetails를 생성하는 방법으로 해결했다. 처음에는 id를 지정해 두면서 값을 못 찾아오는 문제가 있었는데 애초에 세팅한 user의 id를 넣어주면 되는 간단한 문제였다. (물론 해결되니까 간단해 보이는 매직)
이렇게 수정함으로써 각 테스트에서 필요한 데이터는 미리 생성하지만, 테스트 간의 의존성 문제를 최소화할 수 있었다. userDetails로 테스트하는 경우뿐만 아니라, 다른 테이블에서도 비슷한 문제가 발생할 때 이러한 방식으로 적용할 수 있었다.
@BeforeEach
void setUp() {
String email = "1test@test.com";
String encodedPassword = new BCryptPasswordEncoder().encode("qwe123!@#");
String nickname = "1test";
Set<SimpleGrantedAuthority> authorities = Set.of(new SimpleGrantedAuthority("ROLE_USER"));
User user = new User(email, nickname, encodedPassword, UserRoleEnum.USER, true);
userRepository.save(user);
user.updatePassword(encodedPassword);
userDetails = UserDetailsImpl.builder()
.id(user.getId())
.email(email)
.password(encodedPassword)
.nickname(nickname)
.authorities(authorities)
.build();
}
📝 실패한 시도(삽질) 기록
테스트 코드용 데이터베이스로 H2 데이터베이스를 활용하려고 했지만, H2 데이터베이스에서는 "user"가 예약어로 지정되어 있어 User 엔티티가 인식되지 않았다. (이 문제 찾는데도 꽤 걸렸다..ㅎㅎ) 또한, H2 데이터베이스에서 저장된 내용을 시각적으로 확인하기 어려워 답답한 상황이 발생했다.
=> 개발용 데이터베이스로 MySQL을 사용하고 있기 때문에, 테스트용 데이터베이스도 MySQL로 변경하여 일관성을 유지하기로 결정했다. "user" 예약어 관련된 문제도 해결할 수 있었고, MySQL Workbench를 활용하여 실제 데이터베이스 내용을 시각적으로 확인하면서 개발하기로 결정했다.
✨👩💻 ✨
id값 잘 가져온 이후에는 (자잘한 문제 말고) 큰 문제없이 약 100개 정도의 메소드를 만들었다. 뿌듯하게 멘토링 시간에 피드백을 받았는데 청천벽력 같은 소리를 듣고 말았다..! 내가 놓치고 오해한 부분에 대해선 2탄으로 돌아오겠습니다.....
'hanghae99 > 프로젝트' 카테고리의 다른 글
| [부하테스트/JPA] Artillery로 성능 향상을 위한 N+1 문제 해결 과정 (0) | 2024.03.05 |
|---|---|
| [프로젝트 회고] 개인 프로젝트를 마치고 (0) | 2024.03.01 |
| [Spring Boot + Mustache] 템플릿 엔진 적용 시 겪은 문제와 해결 방법 (0) | 2024.02.28 |
| [테스트코드/단위테스트] 테스트코드 작성 시 겪은 문제와 해결 방법 2탄 (0) | 2024.02.27 |
| [Spring Boot] JWT + Security 인증 및 인가 구현 (0) | 2024.02.23 |