김데이의 개발공부

[ TIL ] Day 82, 83 - Express SuperTest 라이브러리 본문

코드잇 Node.js(BE) 부트 캠프/TIL (Today I Learn) 📑

[ TIL ] Day 82, 83 - Express SuperTest 라이브러리

theday365 2026. 1. 22. 18:44
반응형

🗓️ 수업 일자 : 2026.1.21 ~ 22

✨ 오늘의 수업 평가  [ GOOD ]   배움이 팡팡 터진 날 🍿💡

 

지난 웹소캣 강의도 그렇고, 이번 테스트 강의도 그렇고 파트 4 들어오면서 다 이해 안가는 것 투성이었는데

어제 멘토님이 "지금 하는것, 이해만 하는 걸로도 충분히 잘 하고 있다"는 응원에 힘이 생겨서 

오늘 "이해만 하자"라는 마음으로 접근하니 오히려 술술 풀리는 느낌이 든다💪💡😄

 

 

👩‍💻 [개인 프로젝트] 오늘 작업 내용 💻
(내일 시작합니다 ~)

 

📝  오늘 배운 내용  

- 테스트 이론 (리마인드)

- EXPRESS SuperTest 라이브러리 소개

- EXPRESS SuperTest 사용하기

 


1. 테스트 이론 (리마인드)

TEST의 종류

  1. 유닛 테스트 : 특정 타겟팅 한 하나의 함수( = 단일 기능용 함수)를 테스트 하는 것  ex) 환율 변환, 대소문자 변환 등
                        단, 유닛 테스트의 단위를 나눌 때 최소 단위가 달라지는 경우도 있어 "최소 단위" 테스트의 의미로 사용
  2. 통합 테스트 : 하나의 모듈에 연결 된 여러 함수, 코드들을 한번에 테스트 하는 것   ex) API(CRUD) 테스트
  3. E2E 테스트 : End-to-End 테스트, 전체 애플리케이션이 제대로 동작 하는지 테스트 하는 것. 시나리오 베이스를 만들어 순서대로 테스트를 진행.    ex) 웹사이트 로그인 - 내부 사용 - 로그아웃 또는 창 닫음 테스트

 

테스트 시나리오

  • 정의 : 하나의 기능이나 API가 정상 작동하는지 확인하는 계획표, "어떤 상황 → 특정 결과"를 정의
  • 요소 : 상황(어떤 상태, 조건) , 행동(사용자 혹은 시스템의 수행 행동), 예상 결과(최종 결과)
  • 하나의 시나리오에 하나의 핵심 동작만 검증하여 복잡도를 낮추고, 실패 케이스도 반드시 포함해야 함

 

 

2. EXPRESS SuperTest 라이브러리 소개

1) SuperTest 란?

https://www.npmjs.com/package/supertest

  • Express 같은 서버에 실제 HTTP를 보내는 테스트 라이브러리
  • 네트워크 없이도 "컨트롤러, 미들웨어 흐름을 통합 테스트"가능
  • 즉, 일종의 가상 공간(=가짜 네트워크)에서 실제 HTTP 요청 흐름을 검증하는 도구

 

2) JEST + SuperTest 

SuperTest가 가상 네트워크에서 작업하지만, 실제 DB에 연결하는 등 실제 서비스에 영향을 줄 가능성이 있음 

JEST를 사용해 DB, 외부 API 역할등의 의존성을 가상화하고, SuperTest가상 네트워크를 구성해 실제 서비스에는 영향을 끼치지 않는 테스트 환경을 구성

JEST & SuperTest (GPT와 Gemini의 우당탕탕 협업 작품 ㅋㅋ)
JEST & SuperTest (GPT와 Gemini의 우당탕탕 협업 작품 ㅋㅋ)

 

 

3) SuperTest 주요 메소드

  • request(app) : HTTP 리퀘스트를 보내는 것과 동일한 역할을 해 주는 메소드
                             get, post 같은 라우터 메소드와 함께 쿼리파라미터, 헤더, 바디 설정 메소드를 추가로 체이닝 가능
                             결과는 response와 동일한 구조로 전달 받음
const response = await request(app)
   .get('/tasks') // router method
   .query({ sort: 'oldest' }); // set method

expect(response.status).toBe(200); // .status : 응답 코드 확인
expect(response.body).toEqual([]); // .body : 응답 결과(바디) 확인

 

 

  • agent(app) : 인증 / 쿠키 등이 포함된 작업을 할 때, 동일한 상태로 연속된 리퀘스트를 보내기 위해 사용하는 메서드로
                          앞서 본 리퀘스트의 체이닝 메서드이므로 request.agent(app)로 사용 
describe('GET /auth/tasks', () => {
  test('로그인 상태에서 할 일 목록을 반환해야 함', async () => {
    
    // 리퀘스트 작업을 agent로 묶음
    const agent = request.agent(app);

    // 1. 로그인 작업을 진행
    const loginResponse = await agent.post('/login').send({ email: ... });
    expect(loginResponse.status).toBe(200);

    // 2, 로그인 한 상태가 유지된 상황에서 get router 실행
    const tasksResponse = await agent.get('/auth/tasks');
    expect(tasksResponse.status).toBe(200);
    expect(tasksResponse.body.length).toBe(0);
  });

  test('비로그인 상태에서 할 일 목록을 반환해야 하면 안 됨', async () => {
  
    // 로그인 하지 않고 바로 request(app)에서 get router 실행
    const response = await request(app).get('/auth/tasks');
    expect(response.status).toBe(401);
    expect(response.body.message).toBe('토큰이 없습니다.');
  });
});

 

 

 

3. EXPRESS SuperTest 사용하기

1) 환경 셋팅

테스트 환경을 위한 package.json 설치 종류

이름 구분 역할 설치 명령어
jest 라이브러리 test runner, assert, mock 등 실제 테스트 수행 npm install --save-dev
  jest ts-jest @types/jest 
ts-jest 라이브러리 Jest가 TypeScript를 이해하도록 연결
@types/jest 타입 정의 Jest API에 대한 타입 정보
supertest 라이브러리 Express 서버에 HTTP 요청을 보내는 테스트용 도구 npm install --save-dev
  supertest @types/supertest
@types/supertest 타입 정의 supertest API에 대한 타입 정보
dotenv-cli  라이브러리 프로세스 실행 전 환경 구축 npm install dotenv-cli

 

+ 추가 dotenv-cli 란?

기존에 사용하던 dotenv는 ‘코드 안에서(=import)’ 환경변수를 로드하는 라이브러리로, 앱이 실행 된 이후에 "process.env" 값을 구성하게 됩니다. 하지만 테스트 환경의 경우, 앱이 실행되기 전 전체 환경을 컨트롤 해야 하므로 프로세스 실행 전 환경을 구축하기 위하여 해당 라이브러리를 사용합니다 

 

 

.env.test 파일 셋팅 

  • 테스트가 실패하지 않게 최소한의 환경만 설정
  • 필수 요소 : DATABASE_URL (테스트 전용 DB 설정) , NODE_ENV=test (분기용 설정) 
  • 테스트 상황에 따라 인증용 JWT_SECRET 같은 값 설정을 쓸 때도 있음

+추가 dotenv-cli 와 .env.test 의 관계 

두 요소는 각각 독립적인 요소로, JEST와 SuperTest 처럼 테스트 환경을 셋팅하는 협력관계.

.env.test에서는 어떤 환경을 셋팅할 것인지 에 대한 설정을 진행하고, dotenv-cli언제 환경을 구현할 지 설정함

 

 

package.json 셋팅 (테스트 관련 명령어 추가)

"scripts": {
     .. 생략 ..
    "test": "dotenv -e .env.test -- npm run prisma:migrate && dotenv -e .env.test -- jest --coverage",
    "prisma:migrate": "prisma migrate dev"
  },
  
  .. 생략 ..

 

&& 기준으로 앞부분 : dotenv -e .env.test -- npm run prisma:migrate

 

  • .env.test를 프로세스 시작 전에 주입, .env.test 에 작성한 테스트용 DATABASE_URL 사용
  • 테스트 DB에 마이그레이션 적용 ⇒ 스키마 최신 상태 보장

&& : 앞부분 명령어가 실행 되어야 뒷부분이 실행됨. 앞부분 실패 시 테스트 실행 안됨 (안전한 테스트 설정)

 

 

&& 기준으로 뒷부분 : dotenv -e .env.test -- jest --coverage

 

  • 동일한 .env.test 환경 유지
  • Jest 테스트 실행하고, 코드 커버리지 측정

 

 

 

jest.config.js 셋팅 (명령어 npx jest --init 로 자동 생성 가능)

module.exports = {
  testEnvironment: 'node', // Node 환경에서 테스트 실행
  verbose: true, // 테스트 결과를 자세히 출력
  testMatch: ['**/*.test.ts'], //테스트 파일로 인식할 파일 패턴 설정
  transform: {
    '^.+\\.ts$': 'ts-jest',
  }, // TypeScript 테스트 파일을 ts-jest로 변환해 실행
  moduleFileExtensions: ['ts', 'js'],
  // 타입 스크립트 사용하는 경우 import 시 확장자 생략 => 탐색할 파일 타입 순서 설정
};

 

 

2) app.ts / main.ts 분리 작업

기존 코드 구성에서는 app.ts 같은 서비스 접속 파일에서 Express 앱을 바로 실행 시키는 구조였으나,
테스트 환경과 실제 실행 환경에서 Express 앱이 모두 사용되야하므로, app을 export하여 내보냄

  ⇒ 테스트에서는 SuperTest로 사용하고, 실제 실행은 main.ts에서 담당한다.

[기본 구조]
import express from 'express';
import { getTasks, createTask ..} from './task.controller';

const app = express();
app.use(express.json());

app.get('/tasks', getTasks);
app.post('/tasks', createTask);

...(중략)

app.listen(3000, () => console.log(`Server Started on port 3000`));

↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

[변경 구조]

// app.listen(3000, () => console.log(`Server Started on port 3000`)); 구문 제거

export default app;
// test 파일에서도 app을 불러서 express 가상 네트워크 구성 해야하므로 
// app을 export 하고 main.ts에서 서버 오픈

main.ts

import app from './app';

app.listen(3000, () => console.log(`Server Started on port 3000`));

 

 

3) 테스트 단위 설정하기 

describe / test(또는 it) / expect 역할 및 단위

  • describe() : 테스트들의 묶음, 라우터 혹은 미들웨어 같은 함수 하나
  • test() 또는 it() : 특정 상황에서의 특정 결과를 도출하는 역할,
                            외부에서 관찰 가능한 결과 혹은 사용자가 겪는 상황을 기준으로 테스트 단위를 나눔
  • expect : test() 또는 it()의 결과로 나와야 하는 검증 포인트, 하나의 test() 안에 여러 개의 검증이 들어가기도 함 

목표/목적에 따른 test() 분리 방식 

test 1개 & expect 여러 개 test 여러 개 & 각 test 별 expect 1개
  • 하나의 성공 시나리오
  • 결과 속성만 여러 개
  • 과제 / 입문 / 기본 통합 테스트
  • 실패 / 성공이 명확히 다른 의미
  • 상태 코드가 다름
  • 에러 메시지가 다름
  • 테스트가 깨졌을 때 원인을 바로 알고 싶을 때

학원 샘플 코드를 활용하여 테스트 작업 분리
학원 샘플 코드를 활용하여 테스트 작업 분리

 

 

4) Test 코드 작성 및 테스트 결과 확인

미리 package.json에 설정 해 둔 테스트 명령어 npm run test 진행 

  → 프리즈마 실행 화면이 나오고, 마이그레이션 완료 메세지 출력

  → 테스트 시작 메세지가 나오고, 테스트 결과와 커버리지 결과 출력

학원 샘플코드를 기준으로 JEST & SuperTest 진행
학원 샘플코드를 기준으로 JEST & SuperTest 진행

 

 


 

📃 내일은 뭘 배울까 🤔

- 개인 미션 코드로 JEST 적용해서 TEST 실행

반응형