🤔 현업에서 Datasource 설정하는 방법
TestContainers 에서 제공하는 애노테이션으로 쉽게 구성할 수 있다고하지만, 현업에서는 애플리케이션을 작성할 때 데이터베이스 설정 부분을 Spring에서 제공하는 기본 설정으로만 구성하는 경우가 없어서 사용하기 어려워 Datasource 부분을 자바 코드로 작성하는 곳이 많다.
// 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 {
}
# 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();
더 자바, 애플리케이션을 테스트하는 다양한 방법
더 자바, 코드를 조작하는 다양한 방법
테스트 코드 작성의 중요성