인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

강민승님의 프로필 이미지
강민승

작성한 질문수

Practical Testing: 실용적인 테스트 가이드

Business Layer 테스트 (2)

PK값으로 테스트 할 때 질문입니다.

작성

·

285

0

  • 학습 관련 질문을 남겨주세요. 어떤 부분이 고민인지, 무엇이 문제인지 상세히 작성하면 더 좋아요!

  • 먼저 유사한 질문이 있었는지 검색해 보세요.

  • 서로 예의를 지키며 존중하는 문화를 만들어가요.

     

우선, 덕분에 테스트 코드를 작성하는데 많은 도움이 됐습니다!

 

현재 토이프로젝트 진행 중에 PK 값을 Long 타입으로 두고

@GeneratedValue(strategy = GenerationType.IDENTITY) 이 전략을 사용하니,

tearDown을 해도, 전체 테스트에서는 create하고 삭제를 하니, PK인 Long이 1L인 것을 보장을 못하더라구요.

그래서 create하는 메서드의 반환을 void로 했다가 Long 타입으로 반환하는데, 이렇게 하는 것도 좋은 코드인가요..?

@DisplayName("사용자를 조회하면 사용자의 이름, 직업, 전화번호, 성별을 조회한다.")
@Test
void getUserInfo() {
    //given
    Register register = Register.builder()
            .name("name")
            .job(Jobs.STUDENT)
            .phone("010-0000-0000")
            .man(true)
            .build();
    Long id = usersService.registerUser(register);

    //when
    UserResponse userInfo = usersService.getUserInfo(id);

    // then
    assertThat(userInfo.name()).isEqualTo("name");
    assertThat(userInfo.job()).isEqualTo(Jobs.STUDENT);
    assertThat(userInfo.phone()).isEqualTo("010-0000-0000");
    assertThat(userInfo.man()).isEqualTo(true);
}
// 단건 조회
public UserResponse getUserInfo (Long id){
    Users user = usersRepository.findById(id).
            orElseThrow(IllegalArgumentException::new);

    return UserResponse.of(user);
} 

입니다!

답변 2

0

박우빈님의 프로필 이미지
박우빈
지식공유자

안녕하세요, 강민승 님!

getUserInfo()을 테스트하기 위해 먼저 만들어둔 fixture의 id가 필요하신 상황이군요.

접근하신 방법도 나쁘지 않습니다. 다만, 테스트 코드를 위해 프로덕션 코드를 변경하는 것이 마음에 걸리신다면, 다음과 같이 접근하는 방법도 있습니다.

// ...User 생성

List<User> users = userRepository.findAll();
User targetUser = users.get(0);
Long targetUserId = targetUser.getId();

//when
UserResponse userInfo = usersService.getUserInfo(targetUserId);

매 테스트가 끝나고 다른 테스트에서 생성했던 User는 모두 클렌징되었다고 가정한다면,
위 테스트를 수행하는 시점으로 UserRepository에서 모든 User를 조회한다면 하나의 User만 조회될 것입니다.
조회한 User에서 id를 꺼내어 when절에서 사용할 수 있습니다.

감사합니다. 🙂

0

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

님의 질문에 대해 답변드립니다.

테스트 코드에서 PK 값의 일관성 문제로 고민이 많으신 것 같습니다. @GeneratedValue(strategy = GenerationType.IDENTITY) 전략을 사용할 경우, ID 값은 데이터베이스에 의해 자동으로 증가되며, 테스트가 실행될 때마다 초기화되지 않습니다. 이로 인해 각 테스트 사이에 데이터 간 격리(isolation) 문제가 발생할 수 있습니다.

테스트 코드에서 사용자 생성 후 생성된 사용자의 ID를 반환하고, 이 ID를 사용하여 사용자 정보를 조회하는 로직으로 구성한 것은 아주 적합한 접근 방식입니다. 이렇게 함으로써 실제 동작 환경에서 사용자 생성과 조회가 어떻게 이루어지는지를 잘 반영할 수 있으며, 테스트 간의 데이터 격리를 유지할 수 있습니다.

데이터 격리를 위해 테스트 데이터베이스에 @DataJpaTest와 같이 스프링 부트가 제공하는 테스트 어노테이션을 활용하거나, 테스트 전용 데이터베이스를 구성하는 방법도 고려할 수 있습니다. 각 테스트 메서드 실행 후 데이터를 정리(cleanup)하는 작업은 테스트 간의 독립성을 보장하기 위해 중요합니다.

따라서, PK 값을 반환하는 방식은 올바른 접근이며, 테스트가 예상대로 동작하도록 하는데 필수적인 부분입니다. 이와 같은 방식으로 테스트를 구성하는 것이 좋은 코드라고 할 수 있습니다.

도움이 되셨길 바랍니다. 추가적인 질문이 있으시면 언제든지 문의해주세요.

강민승님의 프로필 이미지
강민승

작성한 질문수

질문하기