inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

@DataJpaTest에서 참조하는 Entity 관련 질문 있습니다

144

이진호

작성한 질문수 1

0

개발자 선배님들 안녕하세요. @DataJpaTest 관련해서 궁금한점이 생겨서 질문드립니다.

 

제가 작성한 User Entity에서 Address Entity를 FK로 참조하고 있습니다.

 

여기서 UserRepository의 테스트 코드를 작성할 때

 

AddressRepository도 @Autowired로 등록 후 Address를 먼저 save()로 insert 후에 User Insert 테스트를 작성해야 하나요???

 

이러면 UserRepository의 테스트가 아니라 UserRepository, AddressRepository 두개의 테스트를 작성하는 것이라 좀 이상하다고 생각이 드네요..

 

제가 작성한 코드입니다.

 

package com.kh.bookfinder.repository;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.kh.bookfinder.entity.Address;
import com.kh.bookfinder.entity.User;
import com.kh.bookfinder.entity.UserStatus;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;

@ActiveProfiles("test")
@DataJpaTest
@TestPropertySource(locations = "classpath:application-test.properties")
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class UserRepositoryTest {

  @Autowired
  UserRepository userRepository;
  @Autowired
  AddressRepository addressRepository;

  Address givenAddress;

  @BeforeEach
  public void setup() {
    givenAddress = Address.builder()
        .si("서울특별시")
        .gu("강남구")
        .dong("역삼동")
        .roadFullAddress("역삼역")
        .build();
    addressRepository.save(givenAddress);
  }

  @Test
  public void userInsertTest1() {
    // Given: User가 주어진다.
    User givenUser = User.builder()
        .email("user@mail.kr")
        .password("password")
        .phone("010-1234-5678")
        .nickname("nickname")
        .status(UserStatus.ADMIN)
        .address(givenAddress)
        .build();

    // When: save() 메서드를 호출하여 User를 저장한다.
    User actual = this.userRepository.save(givenUser);

    // Then: actual은 givenUser와 같다.
    assertThat(actual).isNotNull();
    assertThat(actual).isEqualTo(givenUser);
  }

  @Test
  @DisplayName("email은 unique로 중복이 불가능하다")
  public void userInsertTest2() {
    // Given: email이 같은 User가 2개 주어진다.
    User givenUser1 = User.builder()
        .email("user@mail.kr")
        .password("password")
        .phone("010-1234-5678")
        .nickname("nickname")
        .status(UserStatus.ADMIN)
        .address(givenAddress)
        .build();
    User givenUser2 = User.builder()
        .email("user@mail.kr")
        .password("password2")
        .phone("010-5678-1234")
        .nickname("nickname2")
        .status(UserStatus.ADMIN)
        .address(givenAddress)
        .build();

    // When: save() 메서드를 호출하여 givenUser1를 저장한다.
    User actual = this.userRepository.save(givenUser1);
    // And: save() 메서드를 호출하여 givenUser2를 저장한다.
    // Then: Exception이 발생한다.
    assertThatThrownBy(() -> this.userRepository.save(givenUser2))
        .isInstanceOf(DataIntegrityViolationException.class)
        .hasMessageContaining("Duplicate");
  }

  @Test
  @DisplayName("nickname은 unique로 중복이 불가능하다")
  public void userInsertTest3() {
    // Given: email이 같은 User가 2개 주어진다.
    User givenUser1 = User.builder()
        .email("user@mail.kr")
        .password("password")
        .phone("010-1234-5678")
        .nickname("nickname")
        .status(UserStatus.ADMIN)
        .address(givenAddress)
        .build();
    User givenUser2 = User.builder()
        .email("user2@mail.kr")
        .password("password2")
        .phone("010-5678-1234")
        .nickname("nickname")
        .status(UserStatus.ADMIN)
        .address(givenAddress)
        .build();

    // When: save() 메서드를 호출하여 givenUser1를 저장한다.
    User actual = this.userRepository.save(givenUser1);
    // And: save() 메서드를 호출하여 givenUser2를 저장한다.
    // Then: Exception이 발생한다.
    assertThatThrownBy(() -> this.userRepository.save(givenUser2))
        .isInstanceOf(DataIntegrityViolationException.class)
        .hasMessageContaining("Duplicate");
  }
}

 

읽어주셔서 감사합니다..!

datajpatest springboot jpa java test

답변 1

0

인프런 AI 인턴

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

이진호님의 질문에 답변드리겠습니다. @DataJpaTest는 주로 JPA 관련 설정만 로드하여 레포지토리 레이어의 컴포넌트에 대한 테스트를 집중적으로 수행할 때 사용됩니다. 따라서 UserRepository의 테스트 코드를 작성할 때 필요한 Address 엔티티를 먼저 저장하는 것이 올바른 접근입니다. 이는 AddressRepository와 UserRepository를 동시에 테스트하는 것이 아니라, UserRepository 테스트에 필요한 사전 조건을 충족시키기 위한 준비 과정으로 볼 수 있습니다. 실제 애플리케이션에서도 사용자를 저장하기 전에 주소 정보가 미리 존재해야 하는 경우가 많으므로, 이러한 테스트 설정은 실제 사용 사례를 잘 반영하고 있습니다.

또한, @DataJpaTest는 기본적으로 내장된 인메모리 데이터베이스를 사용하여 테스트를 실행하지만, @AutoConfigureTestDatabase(replace = Replace.NONE) 어노테이션을 사용하여 실제 데이터베이스에 대한 테스트를 진행할 수도 있습니다. 이 경우 실제 DB 환경을 그대로 사용하여 데이터가 잘 삽입되고 관계가 올바르게 매핑되는지 확인할 수 있습니다.

따라서, 이진호님이 작성하신 테스트 코드는 굉장히 타당하며 User 엔티티와 연관된 Address 엔티티를 먼저 저장하는 접근 방식은 적절합니다.

읽어주셔서 감사합니다.

인텔리제이 설정 최신화 관련 확인 부탁 드립니다!

0

8

1

띄어쓰기

0

14

1

공부 순서

0

14

1

코딩 문제 사이트 접속 오류

0

15

1

재귀함수 연산법

0

26

2

동일성 동등성

0

20

1

안녕하세요 치킨 디도스 이벤트 보고 흉내내보려 들어왔습니다..

0

25

2

47번 리턴 관련 질문

0

26

1

실무 내용 문의드려요

0

27

2

IO활용-회원관리예제1 샘플코드 문의

0

20

1

join에대해 질문드립니다.

0

22

1

pg사가 있다고 가정하면

0

26

1

코드 질문

0

26

1

중급 1편 학습 방향에 대해 조언 부탁드립니다

0

37

1

To-Do App

0

27

1

twitterdb 연결이 안돼요

1

30

2

강의노트 접속 불가

0

29

2

Kafka Cluster 구성도 질문

0

23

1

26년 1회차 기출 강의

0

60

2

기출문제

0

59

1

정보처리기사 실기 zip

0

45

2

답을언제쯤받아볼수있나요

0

54

2

데이터베이스 노션

0

39

2

형 책 어떻게 받아?

1

60

1