ysk(0soo)
Lifealong
ysk(0soo)
전체 방문자
오늘
어제
  • 분류 전체보기 (238)
    • Java (50)
      • whiteship-java-study (11)
      • Java (28)
      • time (6)
    • Spring (68)
      • JPA (15)
      • Spring (1)
      • SpringBoot (1)
      • SpringMVC (6)
      • Spring Security (22)
      • Jdbc (1)
      • RestDocs (14)
      • log (6)
    • Kotlin (3)
    • Web (2)
      • nginx (1)
    • Database (14)
      • MySQL (5)
      • PostgreSQL (1)
      • SQL (1)
      • Redis (4)
    • C, C++ (0)
    • Git (1)
    • Docker (2)
    • Cloud (3)
      • AWS (3)
    • 도서, 강의 (0)
      • t5 (0)
    • 기타 (7)
      • 프로그래밍 (1)
    • 끄적끄적 (0)
    • CS (14)
      • 운영체제(OS) (2)
      • 자료구조(Data Structure) (9)
    • 하루한개 (12)
      • 우아한 테크코스-10분테코톡 (12)
    • 스터디 (12)
      • 클린 아키텍처- 로버트마틴 (2)
      • JPA 프로그래밍 스터디 (10)
    • 테스트 (34)
      • JUnit (19)
      • nGrinder (2)
      • JMeter (0)
    • Infra (3)
    • 프로그래머스 백엔드 데브코스 3기 (0)
    • 디자인 패턴 (3)
    • Issue (4)
    • system (1)
      • grafana (0)
      • Prometheus (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • github

공지사항

인기 글

태그

  • 인가(Authorization) 처리
  • 가상 스레드
  • java
  • restdocs custom
  • 정규표현식
  • 동등성
  • VirtualThread Springboot
  • AccessDecisionVoter 커스텀
  • tree
  • node exporter basic auth
  • restdocs enum
  • StructuredConcorrency
  • 동일성
  • UserDetailsService
  • AuthenticationException
  • nGrinder
  • 구조화된 동시성
  • 가상 스레드 예외 핸들링
  • scope value
  • querydsl
  • 트랜잭션
  • jpa
  • mysql
  • junit5
  • FilterSecurityInterceptor
  • nginx basic auth
  • AccessDecisionManager
  • 동시성 제어
  • LocalDateTime
  • DataJpaTest

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ysk(0soo)

Lifealong

Spring Boot JPA Test @DataJpaTest 기본 설정
테스트/JUnit

Spring Boot JPA Test @DataJpaTest 기본 설정

2022. 8. 27. 21:50

Spring Boot JPA Test @DataJpaTest 기본 설정

  • jpa관련 테스트(Entity, Repository)를 할때 @DataJpaTest를 이용해서 진행하면 JPA관련 Bean과 @Transactional 어노테이션이 달려있어서 테스트가 끝나면 Configuration만 주입받아서 빠르게 테스트를 진행할 수 있다.
  • @Transactional 어노테이션이 달려있어서 테스트가 끝나면 롤백도 되어서 간단하게 결과를 확인할 수 있는 장점이 있다.
  • MySQL, MSSQL, Oracle 처럼 다른 DB를 연동해서 사용할 수도 있지만, 이 글에서는 in-memory DB인 H2를 연동해서 테스트 하는 방법을 정리하고자 한다.

환경

SpringBoot : 2.7.3

Java : JDK11

MacOS : Monterey 12.5.1

h2 : h2:2.1.214

MacBookPro : 14 M1Pro

JUnit : JUnit5

  • build.gradle
plugins {
    id 'org.springframework.boot' version '2.7.3'
    id 'io.spring.dependency-management' version '1.0.13.RELEASE'
    id 'java'
}
​
group = #
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
​
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}
​
repositories {
    mavenCentral()
}
​
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'com.h2database:h2'
}
​
tasks.named('test') {
    useJUnitPlatform()
}
  • Test Property Source
    • yml 형식을 사용한다.
    • main 디렉토리가 아닌 test 디렉토리의 resources를 사용한다.

  • application-test.yml
spring:
​
  config:
    activate:
      on-profile: test
​
  datasource:
    username: sa
    password:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL
​
  jpa:
    hibernate:
      ddl-auto: create-drop
    properties:
      hibernate.dialect: org.hibernate.dialect.MySQL8Dialect
      hibernate:
        format_sql: true
        globally_quoted_identifiers: true
    show-sql: true
    generate-ddl: true
    database-platform: org.hibernate.dialect.MySQL8Dialect
    database: h2
​
  h2:
    console:
      enabled: true
​
  • spring.config.activate.on-profile : test
    • profile 환경 설정을 test로 한다
  • url : jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL
    • h2 기반 인메모리 휘발성 테스트로 진행할것이기 때문에 h2:mem으로 설정했다.
    • DB_CLOSE_DELAY=-1 :
      • 기본적으로 데이터베이스에 대한 마지막 연결을 닫으면 데이터베이스가 닫힙니다.
      • 데이터베이스를 열린 상태로 유지하기 위해 가상 머신이 살아있는 동안 메모리 내 데이터베이스의 내용을 유지한다
      • http://www.h2database.com/html/features.html#connection_modes
    • DATABASE_TO_UPPER=false:
      • (기본값: true). true로 설정하면 인용되지 않은 식별자와 데이터베이스의 짧은 이름이 대문자로 변환됩니다.
      • 테이블명이나 컬럼 이름을 소문자로 사용하기 위해서 false로 설정
      • DATABASE_TO_LOWER = true로도 사용 가능
      • https://www.h2database.com/javadoc/org/h2/engine/DbSettings.html
    • MODE=MYSQL
      • H2 DB의 호환 모드를 MySQL로 설정
  • globally_quoted_identifiers: true
    • 데이터베이스 테이블 자동 생성시 키워드나 예약어가 충돌되는 경우가 있습니다.
    • true로 설정하면 충돌을 방지하기 위해 테이블명이나 컬럼명을 ` 로 감싸줍니다.
    • https://www.popit.kr/%EA%B0%80%EC%A7%9C%EB%89%B4%EC%8A%A4%EC%95%84%EC%9B%83-%ED%95%98%EC%9D%B4%EB%B2%84%EB%84%A4%EC%9D%B4%ED%8A%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%8A%A4%ED%82%A4%EB%A7%88/
  • 다른 옵션들은 http://www.h2database.com/html/features.html 에 잘 나와있습니다.

Entity, Repository

@Getter
@Entity
@NoArgsConstructor
public class Member {
​
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
​
    @Column(nullable = false)
    private String name;
​
    @Column(nullable = false, unique = true)
    private String email;
​
    @Column(nullable = false)
    private int age;
​
    @Builder
    public Member(String name, String email, int age) {
        this.name = name;
        this.email = email;
        this.age = age;
    }
​
}
​
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
​
}
​

TestClass - MemberRepositoryTest

@ActiveProfiles("test")
@DataJpaTest
@TestPropertySource(locations = "classpath:application-test.yml")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MemberRepositoryTest {
​
    @Autowired
    MemberRepository memberRepository;
​
    @Test
    void save() {
        memberRepository.save(
                Member.builder()
                        .age(1)
                        .email("email@email.com")
                        .name("name")
                        .build()
        );
​
    }
}
  • @ActiveProfiles("test") : 테스트 시에 어떤 profile로 설정할지 구성한다.
    • develop, prod로 설정하면 해당 profile로 실행한다.
    • test 환경 설정으로 실행할것이기 때문에 test로 설정 하였다.
  • @DataJpaTest : Spring에서 JPA 관련 테스트 설정만 로드한다. DataSource의 설정이 정상적인지, 제대로 생성 수정 삭제 조회 하는지 등의 테스트가 가능하다.
  • @TestPropertySource(locations = "classpath:application-test.yml")
    • @TestPropertySource 애노테이션을 사용해서 새로운 설정 Source를 정의하고 프로퍼티의 값을 오버라이딩 한다.
    • locations 속성을 통해서 설정 파일의 위치를 변경할 수 있다. 또한 properties 속성을 통해 우선순위가 더 높은 속성을 추가할 수 있다.
  • @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    • @DataJpaTest를 사용하면 자동으로 EmbededDatabase를 사용하기 때문에 내가 설정한 설정값들을 사용할 수 없다.
    • 이 설정을 replace 해서 해당 설정이 동작하지 않고, 내가 설정한 설정파일대로 만들어진 DataSoruce가 Bean으로 등록된다.
    • yml이나 properties에서 내가 설정한 설정파일대로 사용하려면 (내가 설정한 H2, MySQL,Oracle 등) NONE 옵션을 사용해서 사용해야 한다

반드시 주의해야 하는게,

기본 H2가 아닌 내가 설정한 H2대로 설정하려면

@AutoConfigureTestDatabase 이 옵션을 반드시 추가해야한다 그렇지 않으면 엄청난 고생을 하게 된다.

  • @AutoConfigureTestDatabase는 기본적으로 h2 인메모리 기반 으로 테스트를 하는데 왜????
  • 이 부분은 다른 글로 정리할것이다.. 이틀을 삽질을 했다.. - https://0soo.tistory.com/41
  • syntax error가 무조건 난다..
  • 예약어도 아닌데 테이블도 안만들어지고.. select insert 아무것도 안된다..

  • 정상적으로 테스트가 되는것을 볼 수 있다.

'테스트 > JUnit' 카테고리의 다른 글

Junit5 AssertJ List 정렬 테스트 ( Check if list is sorted in junit)  (0) 2022.12.15
RefectionTestUtils - private 필드 값 주입, private 테스트  (0) 2022.12.13
JUnit5 - Java에서의 단위테스트5 Mock, Mockito, Stup  (0) 2022.08.21
JUnit5 - Java에서의 단위테스트4 Mock, Mockito  (0) 2022.08.21
JUnit5 - Java에서의 단위테스트3 - 테스트 인스턴스들  (0) 2022.08.21
    '테스트/JUnit' 카테고리의 다른 글
    • Junit5 AssertJ List 정렬 테스트 ( Check if list is sorted in junit)
    • RefectionTestUtils - private 필드 값 주입, private 테스트
    • JUnit5 - Java에서의 단위테스트5 Mock, Mockito, Stup
    • JUnit5 - Java에서의 단위테스트4 Mock, Mockito
    ysk(0soo)
    ysk(0soo)
    백엔드 개발을 좋아합니다. java kotlin spring, infra 에 관심이 많습니다. email : kim206gh@naver.com github : https://github.com/devysk

    티스토리툴바