작성
·
79
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");
}
}
읽어주셔서 감사합니다..!
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
이진호님의 질문에 답변드리겠습니다. @DataJpaTest
는 주로 JPA 관련 설정만 로드하여 레포지토리 레이어의 컴포넌트에 대한 테스트를 집중적으로 수행할 때 사용됩니다. 따라서 UserRepository의 테스트 코드를 작성할 때 필요한 Address 엔티티를 먼저 저장하는 것이 올바른 접근입니다. 이는 AddressRepository와 UserRepository를 동시에 테스트하는 것이 아니라, UserRepository 테스트에 필요한 사전 조건을 충족시키기 위한 준비 과정으로 볼 수 있습니다. 실제 애플리케이션에서도 사용자를 저장하기 전에 주소 정보가 미리 존재해야 하는 경우가 많으므로, 이러한 테스트 설정은 실제 사용 사례를 잘 반영하고 있습니다.
또한, @DataJpaTest
는 기본적으로 내장된 인메모리 데이터베이스를 사용하여 테스트를 실행하지만, @AutoConfigureTestDatabase(replace = Replace.NONE)
어노테이션을 사용하여 실제 데이터베이스에 대한 테스트를 진행할 수도 있습니다. 이 경우 실제 DB 환경을 그대로 사용하여 데이터가 잘 삽입되고 관계가 올바르게 매핑되는지 확인할 수 있습니다.
따라서, 이진호님이 작성하신 테스트 코드는 굉장히 타당하며 User 엔티티와 연관된 Address 엔티티를 먼저 저장하는 접근 방식은 적절합니다.
읽어주셔서 감사합니다.