티스토리 뷰
TDD, 클린 코드 with Java 교육
중에 메모리 DB를 효율적으로 사용할 수 있는 방법을 배워, 샘플 코드와 함께 정리를 해두려고 한다. 이걸 잘 활용하면, 실무에서 초기 개발 환경 세팅을 눈에 띄게 편하게 만들 수 있을 것 같다 🔥
1. 개요
기존 방식의 문제점: 테스트용 파일 DB
그동안 실무에서 DB에 의존적인 코드를 테스트하기 위해서는 아래와 같은 순서로 보통 작업을 했었다. 문제는 테스트를 위한 DB 파일을 관리해야 한다는 것이고, 테이블이 변경될 때마다 DB 파일도 함께 업데이트 해야한다는 점이다.
- (h2 기준으로) 테스트용 DB 파일 생성
- properties(혹은 yml)에 DB 경로 설정
- 테이블이 변경될 경우, 테스트용 DB 파일을 수정
인메모리 DB가 있다는 건 알고 있었지만, test fixture
를 위해 어디에선가는 DB에 insert를 해줘야했기 때문에 파일 DB를 쓰는게 낫다라고 생각했었다.
개선: 어플리케이션 실행 시, DDL, DML 스크립트 실행
스프링 어플리케이션 실행 시 resources
경로에 있는 schema.sql
(DDL)과 data.sql
(DML) 스크립트를 실행하는데, 이를 활용하면 테스트를 위한 DB 파일을 사용하지 않고 인메모리 DB를 활용해 테스트를 수행할 수 있다.
2. 프로젝트 준비
build.gradle 설정
스프링 부트 버전은 2.7.12
이고, DB는 h2
와 hibernate
로 테스트 하기 위해 의존성은 아래와 같이 추가했다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
}
schema.sql(ddl)
샘플이 될 예제는 최대한 간단히 만들었다.
create table book (
id bigint,
title varchar(255),
price integer,
primary key (id)
);
data.sql(dml)
insert into book values(1, 'TDD', 12000);
insert into book values(2, 'CLEAN CODE', 19000);
insert into book values(3, 'JPA', 18000);
application.yml
인메모리 DB를 위한 설정과 hibernate를 통해 ddl이 실행되지 않도록 spring.jpa.hibernate.ddl-auto: none
설정
spring:
datasource:
url: jdbc:h2:mem:testdb
jpa:
hibernate:
ddl-auto: none
logging.level:
org.hibernate.SQL: debug
org.springframework.jdbc: debug
3. 어플리케이션 구성
domain
위에서 작성한 book 테이블과 매핑되는 엔티티
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@EqualsAndHashCode
public class Book {
@Id
private Long id;
private String title;
private int price;
}
infrastructure
@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
}
4. 테스트
테스트는 별도의 test fixture
를 생성하지 않고, book 테이블 레코드를 모두 읽어서 결과를 비교했다. 인메모리 DB를 사용하고 있으므로, 초기 데이터가 insert되지 않으면 성공할 수 없지만…
@SpringBootTest
class LoadingInitialDataTestApplicationTests {
@Autowired
private BookRepository bookRepository;
@Test
void find_all() {
List<Book> foundBooks = bookRepository.findAll();
assertThat(foundBooks).containsExactlyInAnyOrder(
new Book(1L, "TDD", 12000),
new Book(2L, "CLEAN CODE", 19000),
new Book(3L, "JPA", 18000)
);
}
}
테스트 결과: 성공
ddl, dml
테스트 시, create, insert문이 수행되는 것을 로그로 확인할 수 있다.
select
당연히 select문도 수행
샘플 코드 🤓
참고 자료 🙇♂️
'스프링' 카테고리의 다른 글
[Spring] 어플리케이션 종료 시 들어온 요청은 처리하고 마치기(graceful shutdown) (0) | 2023.11.05 |
---|---|
[Spring] 어플리케이션을 종료할 때 특정 작업 수행하기(feat. ApplicationListener) (0) | 2023.11.05 |
[Spring] @SpringBootApplication가 없는 상황에서 @SpringBootTest 수행하기 (0) | 2023.08.05 |
[Spring] 주기적인 작업 구현하기(feat. Scheduling Tasks) (0) | 2023.04.01 |
[Spring Integration] 소개 및 튜토리얼 (0) | 2023.03.18 |