문제 상황
1.
h2라는 데이터베이스에서는 인메모리로 데이터베이스를 만들어 주는 기능을 제공한다.
2.
인메모리 데이터베이스는 local에 데이터베이스를 따로 세팅하지 않아도 JVM에서 간편하게 데이터베이스를 사용할 수 있다. 따라서 테스트용 데이터베이스 구축을 쉽게 만들 수 있다.
3.
서비스용 데이터베이스와 테스트용 데이터베이스(인메모리 디비)를 나누어 설정하는 간편한 방법을 찾고싶다.
결과
이 글을 통해 만드는 환경은 다음과 같다.
1.
서비스하는 데이터베이스용 application-local.yml을 만든다. (여기서는 mariadb를 이용 할 것이다.)
2.
테스트를 하기위한 인메모리 데이터베이스용 application-test.yml 을 만든다. (H2를 이용 할 것이다.)
3.
서비스용 데이터베이스와 테스트용 데이터베이스가 잘 작동하는지 확인한다.
gradle
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // 1
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client' // 2
// test
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.springframework.boot:spring-boot-starter-test' // 3
testRuntimeOnly 'com.h2database:h2' // 4
}
test {
useJUnitPlatform()
}
Groovy
복사
•
1) spring jpa를 사용하기 위해서 추가했다.
•
2) 서비스에서 mariadb를 사용하기 위해 추가했다.
•
3) spring을 test코드에 잘 적용하기 위해 추가했다.
•
4) test에서는 h2를 사용하기 위해 추가했다.
서비스용 데이터베이스 만들기
# application-local.yml # application-{profile_name}.yml 을 이름으로 결정한다.
spring:
config:
activate:
on-profile: local # profile이름은 local로 설정
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/test_db?serverTimezone=Asia/Seoul
username: testuser
password: userpassword
jpa:
hibernate:
ddl-auto: create # 1
database-platform: org.hibernate.dialect.MariaDB103Dialect
YAML
복사
•
1) ddl 생성에 대한 설정을 한다.
◦
create: 매번 데이터베이스를 생성하고 끝날 때 삭제하지 않는다.
◦
create-drop: 데이터베이스를 생성하고 끝날 때 삭제한다.
◦
update: 엔티티 구조에 따라 데이터베이스를 변경한다.
◦
none: 아무런 동작도 하지 않는다.
◦
validate: 데이터베이스 스키마를 검증한다.
테스트용 데이터베이스 만들기
# application-test.yml
spring:
config:
activate:
on-profile: test
datasource:
url: jdbc:h2:mem:testdb
username: sa
password: password
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
database-platform: org.hibernate.dialect.H2Dialect
YAML
복사
데이터베이스 확인
# docker-compose.yml
version: "3.8"
services:
mariadb:
image: mariadb:latest
environment:
MARIADB_ROOT_PASSWORD: rootpassword
MARIADB_DATABASE: test_db
MARIADB_USER: testuser
MARIADB_PASSWORD: userpassword
ports:
- "3306:3306
YAML
복사
서비스용 db를 생성하는 docker compose file
Test용 코드
application.yml
# application.yml
spring:
profiles:
default: local
jpa:
properties:
hibernate:
show_sql: true # 1
format_sql: true # 2
globally_quoted_identifiers: true # 3
YAML
복사
•
1) 모든 sql을 콘솔의 기록합니다.
•
2) sql을 예쁘게 기록한다.
•
3) sql문에서 식별자를 keyword도 사용할 수 있습니다. (sql문에서 식별자를 큰따옴표로 묶습니다.)
java 예제코드
// main/java/org/example/Main
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Java
복사
// main/java/org/example/User
package org.example;
import javax.persistence.*;
@Entity
@Table(name = "USER")
public class User {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "USER_ID")
private Long id;
@Column(name = "ROW")
private String row;
@Column(name = "COLUMN")
private String column;
public Long getId() {
return id;
}
public String getColumn() {
return column;
}
public String getRow() {
return row;
}
public User(String row, String column) {
this.row = row;
this.column = column;
}
public User() { }
}
Java
복사
// main/java/org/example/UserRepository
package org.example;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
Java
복사
Main을 실행하면 mariadb로 잘 연결되었다는 것을 확인할 수 있다.
java test코드
아래는 Test환경에서 h2데이터베이스를 사용하는 코드이다.
// test/java/org/example/UserRepositoryTest
package org.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@ActiveProfiles("test")
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void testConnection() {
assertTrue(userRepository.findAll().isEmpty());
User user = new User("row", "column");
user = userRepository.save(user);
User cmp = userRepository.findById(user.getId()).orElseThrow();
assertEquals(user.getId(), cmp.getId());
assertEquals(user.getRow(), cmp.getRow());
assertEquals(user.getColumn(), cmp.getColumn());
}
}
Java
복사
위 테스트 코드를 실행하면 h2를 이용한 코드가 생성되는 것을 볼 수 있다.
@ActiveProfiles 어노테이션을 통해 여러가지 profile을 골라서 추가할 수 있다.
gradle을 사용하고 @ActiveProfiles를 사용하지 않는 방법
만약 test코드에서 @ActiveProfiles 를 계속 붙이는 것이 번거롭다면 gradle 설정을 바꾸어 해결할 수도 있다.
test {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'test'
}
Groovy
복사
test 부분을 위와같이 고치면 자동으로 test환경에서 profile이 test가 된다.