inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

143

이진호

작성한 질문수 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 엔티티를 먼저 저장하는 접근 방식은 적절합니다.

읽어주셔서 감사합니다.

실습 권한이 없네요··· 이건 ··· 좀··· 401 에러떠요

0

9

1

inheritance startegy 선택시 고려사항

0

11

0

[할인쿠폰] 코테의 바이블[JAVA] 50% 할인 쿠폰 관련

0

13

1

Entity 동등성 비교

0

14

1

패키지 구분에 대해 궁금한게 있습니다

0

20

2

안녕하세요. 바뀐 채점사이트 관련해서 문의드립니다.

0

19

1

스프링부트 서버 에러나요

0

21

1

갑자기 채점 사이트가 바뀌었어요

0

26

1

문제 리스트 페이지

0

25

1

part8 Notion 링크

0

25

1

채점 사이트 관련 질문드립니다

0

21

1

인텔리제이 MCP 서버 설정 관련

0

34

2

조회속도 개선에서 더 개선하는 방법이 궁금합니다.

0

34

2

필기자료 사라졌나요?(실기 일주일만에 안돼서 재도전-_-)

0

40

2

질문있습니다

0

28

1

1번 문제 질문입니다.

0

33

1

26년 1회 실기 해설 강의

0

58

2

음악플레이어 문제 중 코드질문

0

26

1

잠겨버린 사물함 시간초과 관련 질문입니다.

0

28

1

RepositoryTest의 패키지 위치가 domain인 이유

0

31

2

도메인 모델에서 관계와 규칙을 구분하는 방법

0

41

2

16 강의 메세지 retryCount의 의도

0

25

2

JPA Repository 질문이 있습니다!

1

35

2

페이지네이션 처리를 쿼리에서 하는 방식 질문

1

37

1