✍️ 개발 기록
[🎵MIML] H2 DB를 이용하여 Mocking 없이 테스트 하기
ming412
2023. 11. 10. 02:14
스터디를 진행하며 주 1회 발표를 준비하는데, 이번주 발표를 준비하다가 테스트 코드를 작성하게 되었다.
Mocking을 이용해 Service나 Repository를 새로 주입할 수 있지만 Entity가 많아지고 데이터가 쌓이다보면 극악의 생산성을 보여준다..
따라서 Mocking 하지 않고 데이터베이스에 init data를 넣어두고, 실제 데이터베이스 값을 변경하며 테스트를 할 예정이다. (테스트용 DB는 H2를 사용했다.)
테스트 실행 시 일어나는 일은 아래와 같다.
1. 기존 테이블이 있다면 drop
2. schema.sql을 실행하여 새로 테이블 생성
3. data.sql을 실행하여 테이블에 init data를 삽입
4. 테스트 실행
1. gradle 세팅
// H2
implementation 'com.h2database:h2'
2. application-test.yml
spring:
sql:
init:
mode: always # 항상 init data 생성
jpa:
defer-datasource-initialization: true # 항상 init data 생성
database-platform: org.hibernate.dialect.MySQL5Dialect
database: h2
show-sql: true
open-in-view: false
properties:
hibernate:
show_sql: true
format_sql: true
generate-ddl: true
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb;MODE=MySQL; # In-Memory mode: 로컬에 데이터를 저장하지 않고 메모리 상에서만 데이터가 저장된다.
username: SA
password:
h2:
console:
enabled: true
path: /h2-console
logging.level:
org.hibernate.SQL: debug # 로그의 ?에 어떤 값이 들어갔는지 확인할 수 있다.
3. 더미 데이터 파일 추가
애플리케이션 실행 시 더미 데이터를 추가하기 위해 `schema.sql`과 `data.sql`을 작성한다.
위치는 `resources` 하위에 생성하면 읽어올 수 있다.
schema.sql
-- user_tb 테이블 생성
DROP TABLE IF EXISTS user_tb cascade;
CREATE TABLE `user_tb` (
`user_id` bigint NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`user_id`)
);
-- board_tb 테이블 생성
DROP TABLE IF EXISTS board_tb cascade;
CREATE TABLE `board_tb` (
`board_id` bigint NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`board_id`)
);
-- board_role_tb 테이블 생성
DROP TABLE IF EXISTS board_role_tb cascade;
CREATE TABLE `board_role_tb` (
`board_role_id` bigint NOT NULL,
`boardRoleType` varchar(255) DEFAULT NULL,
`board_id` bigint DEFAULT NULL,
`user_id` bigint DEFAULT NULL,
PRIMARY KEY (`board_role_id`),
FOREIGN KEY (`board_id`) REFERENCES `board_tb`(board_id),
FOREIGN KEY (`user_id`) REFERENCES `user_tb`(user_id)
);
data.sql
INSERT INTO user_tb (user_id, name) VALUES (1, '민주');
INSERT INTO user_tb (user_id, name) VALUES (2, '지영');
INSERT INTO board_tb (board_id, name) VALUES (1, '자유게시판');
INSERT INTO board_tb (board_id, name) VALUES (2, '인기게시판');
INSERT INTO board_role_tb (board_role_id, boardRoleType, board_id, user_id) VALUES (1, 'ADMIN', 1, 1);
INSERT INTO board_role_tb (board_role_id, boardRoleType, board_id, user_id) VALUES (2, 'ADMIN', 1, 2);
INSERT INTO board_role_tb (board_role_id, boardRoleType, board_id, user_id) VALUES (3, 'NORMAL', 2, 1);
4. 테스트코드 작성
@ActiveProfiles("test") // application-test.yml을 읽어오겠다.
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Autowired
private BoardRoleRepository boardRoleRepository;
// ...
}
5. H2 DB 연결 완료
테스트 코드를 실행했을 때 H2 DB가 성공적으로 연결된 것을 확인할 수 있다!
이로써 불필요한 mocking으로 인해 데이터의 정합성을 의심할 필요도 없고 추가적인 코드를 작성할 필요도 없어졌다.
DB통신으로 인해 발생될 Service의 로직실패를 함께 확인하고 데이터 조합 등 여러 상황을 테스트 할 수 있다.
🔗 참고
H2 DB를 이용한 Mocking 없이 편하게 테스트 하기
[Spring | test | H2] test에서 H2 DB 연결하기
Spring boot에서 H2 DB 3가지 모드 사용하기(embedded, In-Memory, Server)
[JUnit5] Spring Boot Test DB 분리
SpringBoot - H2 데이터베이스 - CRUD 코드 작성, 테스트