테스트용 DB 분리하기

June·2022년 5월 15일
0

우테코

목록 보기
42/84

학습 배경

체스 미션을 하면서 처음에는 단순히 FakeDao 인터페이스를 구현해서 실제 Dao를 사용하지 않고 테스트를 했다. 하지만 테이블이 복잡해지면서 FakeDao를 만드는 것도 부담이 되었다.

또한 Dao를 테스트 할 때 실제 DB를 이용해서 테스트하는 것도 부적절하다고 생각했다. 왜냐하면 실제 서비스를 제공하고 있는 DB에 테스트를 한다고 데이터를 조작하면 롤백한다고 해도 성능의 문제도 있고 다른 위험도 있을 것 같았기 때문이다.

DB 분리하기

FakeDao

테스트 더블을 이용하는 방법이다.

FakeDao


public class FakeChessBoardDao implements ChessBoardDao {

    Map<Position, Piece> repository = new HashMap<>();

    @Override
    public void save(Position position, Piece piece, int roomId) {
        repository.put(position, piece);
    }

    @Override
    public Map<Position, Piece> findAllPieces(int roomId) {
        return repository;
    }

    @Override
    public void movePiece(MoveDto moveDto, int roomId) {

    }

    @Override
    public ChessCellDto findByPosition(int roomId, String position) {
        return null;
    }

    @Override
    public boolean boardExistInRoom(int roomId) {
        return true;
    }
}

하지만 위에서 말했듯이 이 방법은 실용적이지 못하다. DB가 커지며 FakeDao를 유지하기 위한 비용이 커지며, DB와 엄연히 다른 환경이다. 예를 들어 DB에서 중복된 id가 있을 때 반환되는 예외 같은 것을 이런 것에서는 흉내내려면 비용이 많이 든다.

DB 분리

체스 미션 코드 중

프로덕션의 application.properties가 아닌 test의 application.properties가 읽히는지 테스트하기 위해 테스트에 my.name이라는 프로퍼티에 이름을 할당해놨다.

실제로 이름이 잘 출력되는 것을 통해 테스트의 application.properties가 읽히는 것을 확인할 수 있었다.

미션을 할 때에는 java 하위에 resources 디렉토리를 만들었다. 그래서 테스트를 해도 테스트를 위한 설정들을 읽어들이지 못했다! 반드시 resources 디렉토리를 생성 후 일반 디렉토리 아이콘과 다른지 확인하자.

이렇게 하면 테스트 시에 test/resources/application.properties를 읽어서 설정 파일들을 읽어온다.

또한 처음 테이블을 test-schema.sql에서 읽어와서 테스트용 DB를 만든다.

Initialize a Database Using Basic SQL Scripts 공식 문서

test-schemal.sql

DROP TABLE board IF EXISTS;
DROP TABLE room IF EXISTS;

create table room
(
    id int(10) NOT NULL AUTO_INCREMENT,
    title varchar(255),
    password varchar(255) NOT NULL,
    color varchar(5) NOT NULL DEFAULT 'WHITE',
    finished boolean default 0,
    deleted boolean default 0,
    primary key (id)
);

create table board
(
    board_id int(10) NOT NULL AUTO_INCREMENT,
    position varchar(2) NOT NULL,
    piece varchar(10) NOT NULL,
    room_id int(10) NOT NULL,
    primary key (board_id),
    foreign key (room_id) references room (id)
);

insert into room (title, password, color) values ('testTitle', 'testPassword', 'WHITE');
insert into board (position, piece, room_id) values ('a2', 'p_WHITE', 1);

미션을 할 떄는 schema.sql에서 테이블도 생성하고 기본 데이터도 넣었다. 하지만 공식 문서를 보다보니 DDL(스키마 생성)과 DML(데이터 삽입, 삭제 등)을 구분하는 것이 명확하겠다라는 생각이 들었다.

0개의 댓글