통합테스트를 할 때 Docker를 통해 테스트 DB를 띄우고, 마이그레이션 파일을 적용해 스키마를 동기화시키는데, 간혹 마이그레이션 파일들을 적용하기 전에 DB 연결문제로 실패하는 경우가 있다.
테스트 사전 세팅을 package.json의 pre script로 수행하니까 임시로 sleep을 주었지만, 더 나은 해결책을 찾은 것 같아서 기록으로 남긴다.
현재 script가 아래와 같다고 가정하고, pre script의 sleep을 변경해보자.
해당 글에서 테스트 DB는 postgresql을 사용합니다.
package.json
"pretest:integration": "docker compose up -d && sleep 1 && npx prisma migrate dev"
"test:integration": jest .....
"posttest:integration": "docker compose down"
먼저 docker compose 파일을 하나 작성해주자.
name: test-setup
services:
postgresql:
container_name: test-postgresql
image: postgres
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_PASSWORD: test
POSTGRES_DB: test_1234
그리고 스크립트를 하나 작성하자.
wait-for-postgres.sh
#!/bin/sh
RETRY=0
MAX_RETRY=3
until docker exec test-postgresql pg_isready;
do
>&2 echo "waiting for postgresql ready...retry count: $RETRY"
sleep 1
RETRY=$((RETRY+1))
if [ $RETRY -ge $MAX_RETRY ]; then
>&2 echo "failed to connect postgresql after $MAX_RETRY retries"
exit 1
fi
done
간단히 살펴보자면...
위에서 만든 test-postgresql 컨테이너에 접속해서 pg_isready
명령어를 날린다.
pg_isready
명령어는 postgresql 서버에 접속을 시도하고 성공하면 0, 실패하면 1~3 값을 반환한다고 하니 실패하는 동안 until문이 계속 참이 되어 다시 시도하게 된다.
그리고 설정한만큼 재시도하고 종료하는데 이건 선택적으로 적용하면 될 것 같다.
이제 script 파일의 sleep을 해당 파일을 실행하는 것으로 변경해보자.
"pretest:integration": "docker compose up -d && sh ./script/wait-for-postgres.sh && npx prisma migrate dev"
"test:integration": jest .....
"posttest:integration": "docker compose down"
그리고 일부러 한번 실패해보면
Error response from daemon: No such container: test-postgresql
waiting for postgresql ready...retry count: 0
Error response from daemon: No such container: test-postgresql
waiting for postgresql ready...retry count: 1
Error response from daemon: No such container: test-postgresql
waiting for postgresql ready...retry count: 2
failed to connect postgresql after 3 retries
성공했을 때는 아래와 같이 정상적으로 접속되었다는 메시지가 출력된다.
/var/run/postgresql:5432 - no response
waiting for postgresql ready...retry count: 0
/var/run/postgresql:5432 - accepting connections