체스 미션을 하면서 처음에는 단순히 FakeDao
인터페이스를 구현해서 실제 Dao를 사용하지 않고 테스트를 했다. 하지만 테이블이 복잡해지면서 FakeDao
를 만드는 것도 부담이 되었다.
또한 Dao를 테스트 할 때 실제 DB를 이용해서 테스트하는 것도 부적절하다고 생각했다. 왜냐하면 실제 서비스를 제공하고 있는 DB에 테스트를 한다고 데이터를 조작하면 롤백한다고 해도 성능의 문제도 있고 다른 위험도 있을 것 같았기 때문이다.
테스트 더블을 이용하는 방법이다.
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가 있을 때 반환되는 예외 같은 것을 이런 것에서는 흉내내려면 비용이 많이 든다.
체스 미션 코드 중
프로덕션의 application.properties
가 아닌 test의 application.properties
가 읽히는지 테스트하기 위해 테스트에 my.name
이라는 프로퍼티에 이름을 할당해놨다.
실제로 이름이 잘 출력되는 것을 통해 테스트의
application.properties
가 읽히는 것을 확인할 수 있었다.
미션을 할 때에는 java 하위에 resources 디렉토리를 만들었다. 그래서 테스트를 해도 테스트를 위한 설정들을 읽어들이지 못했다! 반드시 resources 디렉토리를 생성 후 일반 디렉토리 아이콘과 다른지 확인하자.
이렇게 하면 테스트 시에 test/resources/application.properties
를 읽어서 설정 파일들을 읽어온다.
또한 처음 테이블을 test-schema.sql
에서 읽어와서 테스트용 DB를 만든다.
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(데이터 삽입, 삭제 등)을 구분하는 것이 명확하겠다라는 생각이 들었다.