테스트/JUnit

Spring Boot JPA Test @DataJpaTest 기본 설정

ysk(0soo) 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로 한다

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 아무것도 안된다..

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