JPA 심화 4-2

5w31892p·2023년 2월 5일
0

JPA 심화

목록 보기
17/19

TestContainer 로 배포환경과 동일한 DB에서 테스트 하기

:: TestContainers

  • 도커 환경에서 데이터베이스를 실행하여 테스트 환경을 쉽게 구축할 수 있게 해주는 라이브러리
  • 개발 환경에 데이터베이스를 사용하지 않기 때문에 테스트 때문에 발생하는 더미 데이터를 줄일 수 있다.
  • H2와 같은 인메모리 DB를 사용하는 것이 아니라서 실제 환경과 거의 비슷한 환경으로 데이터베이스를 테스트할 수 있다.
  • 테스트가 느려지는 단점이 있다.

🤔 현업에서 Datasource 설정하는 방법
TestContainers 에서 제공하는 애노테이션으로 쉽게 구성할 수 있다고하지만, 현업에서는 애플리케이션을 작성할 때 데이터베이스 설정 부분을 Spring에서 제공하는 기본 설정으로만 구성하는 경우가 없어서 사용하기 어려워 Datasource 부분을 자바 코드로 작성하는 곳이 많다.

TestContainers 실무 사용예시

// build.gradle

testImplementation "org.testcontainers:testcontainers:1.17.6"
testImplementation 'org.testcontainers:junit-jupiter:1.17.6'
testImplementation 'org.testcontainers:mysql:1.17.6'
# application.yml

spring:
  profiles:
    active: local
  jpa:
    database: mysql
    database-platform: org.hibernate.dialect.MySQL8Dialect
    open-in-view: false
    properties.hibernate:
      hbm2ddl.auto: create-only
      enable_lazy_load_no_trans: false
      implicit_naming_strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
      physical_naming_strategy: org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
      default_batch_fetch_size: 100
  data:
    web:
      pageable:
        default-page-size: 20 # page 파라미터 없을 경우에 default 값
        max-page-size: 100 # size 파라미터 없을 경우에 default 값
        one-indexed-parameters: true # 페이지 시작을 1부터 (currentPage - 1)
logging:
  config: classpath:log4j2.xml

decorator:
  datasource:
    p6spy:
      enable-logging: true # p6spy 활성화 여부
// ContainerDataSourceConfiguration.java

import javax.sql.DataSource;

import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

import com.zaxxer.hikari.HikariDataSource;

@Configuration
public class ContainerDataSourceConfiguration {
	private static final MySQLContainer<?> MY_SQL_CONTAINER = new MySQLContainer<>(DockerImageName.parse("mysql:8.0.27"))
		.withDatabaseName("ci")
		.withUsername("teasun")
		.withPassword("pass");

	static {
		MY_SQL_CONTAINER.start();
	}

	@Bean
	public DataSource dataSource() {
		return DataSourceBuilder.create()
			.type(HikariDataSource.class)
			.url(MY_SQL_CONTAINER.getJdbcUrl())
			.driverClassName(MY_SQL_CONTAINER.getDriverClassName())
			.username(MY_SQL_CONTAINER.getUsername())
			.password(MY_SQL_CONTAINER.getPassword())
			.build();
	}

}
// @RepositoryTest.java
// 테스트 시 반복적으로 사용하는 어노테이션 모아둔 후 @interface 해서 사용

@DataJpaTest(excludeAutoConfiguration = {DataSourceAutoConfiguration.class, TestEntityManagerAutoConfiguration.class, DataSourceConfiguration.class})
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Import({ContainerDataSourceConfiguration.class, JpaConfiguration.class, QueryDslConfiguration.class})
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepositoryTest {
}

GitHub 실습 코드


:: FixtureMonkey

  • 네이버에서 만든 테스트 생성 객체를 자동으로 생성해주는 자바 라이브러리
  • Mock 객체를 보다 쉽게 생성하기 위해서 사용
  • 실무가서 이런 것 사용 추천 말하면 칭찬 받을 것 (ㅋㅋㅋ)

FixtureMonkey 맛보기

# build.gradle
testImplementation 'com.navercorp.fixturemonkey:fixture-monkey:0.4.9'
testImplementation 'com.navercorp.fixturemonkey:fixture-monkey-javax-validation:0.4.9'
// UserFixture.java

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserFixture {
	private Long userId;
	@NotNull
	private UserType type;
	@NotNull
	private UserStatus status;

	public User toEntity() {
		return User.builder()
			.userId(userId)
			.type(type)
			.status(status)
			.build();
	}
}

생성 예시

var fixturemonkey = FixtureMonkey
		.labMonkeyBuilder()
		.objectIntrospector(BeanArbitraryIntrospector.INSTANCE)
		.plugin(new JavaxValidationPlugin())
		.build();

var user = fixturemonkey.giveMeBuilder(UserFixture.class)
			.set("userId", FixtureMonkeyUtils.getUserId())
			.build()
			.sample()
			.toEntity();

:: 테스트 간단 정리

  • 단위 테스트
    • 각 계층(클래스) 별로 테스트 케이스 작성
  • 통합 테스트
    • 실행될 때마다 랜덤하게 변경되는 시나리오를 만들고 그에 따른 데이터를 미리 생성(Docker 환경의 데이터베이스)
    • 모든 엔드포인트에 대해서 테스트
    • 사전에 데이터를 미리 만들어둔 것을 통해서, 결과를 예측하고 검증할 수 있음
  • 단위테스트는 Pull Request 에서 검증하는 용도(CI)
  • 통합테스트는 정기 배포 당일 생성한 브랜치에 대해서 검증하고 검증이 완료된다면 자동으로 배포하는 프로세스(CD)

참조 사이트

더 자바, 애플리케이션을 테스트하는 다양한 방법
더 자바, 코드를 조작하는 다양한 방법
테스트 코드 작성의 중요성

0개의 댓글