데브코스

[19주차 - DAY5] 웹 기반 문서 편집기 제작 프로젝트(4)

미안하다 강림이 좀 늦었다 2024. 7. 5. 15:32

 

 

BE 단위 테스트

라이브러리 설치

npm install cookie-parser jsonwebtoken
npm install -D jest ts-jest supertest @types/cookie-parse @types/jest

 

테스트 설정

jest.config.js

module.exports = {
   preset: "ts-jest",
   testEnvironment: "node",
};

 

tsconfig.json

{
   "compilerOptions": {
     // ...
   },
   "include": ["src"],
   "exclude": ["src/**/*.test.ts", "src/**/__mocks__/*.ts"]
}

 

users/test.ts 파일에 테스트 케이스를 구현한다.

describe의 expect 부분이 응답의 상태 코드와 body를 검사하는 코드이다.

import request from "supertest";
import { app } from "../app";
import { User, MOCK_USERS } from "../models/__mocks__/user";

jest.mock("../models/user", () => jest.requireActual("../models/__mocks__/user"));
afterEach(() => {
    MOCK_USERS.splice(0, MOCK_USERS.length);
});

describe("GET /users/me", () => {
    test("올바른 JWT 쿠키가 설정되어있으면 유저 정보와 함께 200 응답을 받는다.", async () => {
        MOCK_USERS.push(new User(1, "apple@example.com", "mock_encrypted_apple123"));
        const response = await request(app)
            .get("/users/me")
            .set("Cookie", "access-token=mock_jwt_apple@example.com");
        expect(response.status).toBe(200);
        expect(response.body).toEqual({ email: "apple@example.com" });
    })
});

 

 

FE 단위 테스트

라이브러리 설치

npm install @testing-library/jest-dom @testing-library/react @testing-library/user-event

 

jest 모듈 이름 매핑 설정

package.json 파일에 다음 내용을 추가한다.

"jest": {
    "moduleNameMapper": {
        "^@/(.+)": "<rootDir>/src/$1"
    }
}

 

테스트

JoinForm.test.tsx 파일을 다음과 같이 작성하여 테스트를 진행할 수 있다.

import { fireEvent, screen } from "@testing-library/react";
import { renderWithRouter } from "@/utils/test/renderWithRouter";
import { JoinForm } from "./JoinForm";
describe("JoinForm", () => {
    test("잘 렌더링된다.", () => {
        renderWithRouter(<JoinForm />);
        expect(screen.getByLabelText("이메일", { selector: "input" })).toBeInTheDocument();
        expect(screen.getByLabelText("비밀번호", { selector: "input" })).toBeInTheDocument();
        expect(screen.getByLabelText("비밀번호 확인", { selector: "input" })).toBeInTheDocument();
        expect(screen.getByText("회원가입", { selector: "button" })).toBeInTheDocument();
        expect(screen.getByText("로그인하기", { selector: "a" })).toBeInTheDocument();
    });
    test("회원정보를 입력하고 회원가입 버튼을 누르면 onSubmit 콜백이 호출된다.", () => {
      // ...
    });
    test("로그인하기 버튼을 누르면 로그인 URL로 이동한다.", () => {
      // ...
    });
    test("비밀번호 확인을 다르게 입력하면 alert 창이 뜨고 onSubmit 콜백이 호출되지 않는다.", () => {
      // ...
    });
});

 

 

BE 컨테이너화

Dockerfile 작성

FROM node:18
WORKDIR /var/app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY ./build/ ./build/
ENV PORT=3031
 CORS_ALLOWED_ORIGIN=(...)
EXPOSE 3031
HEALTHCHECK CMD curl --fail http://localhost:3031/healthcheck || exit 1
ENTRYPOINT ["node", "."]

 

데이터베이스 구성

version: "3.8"
services:
 db:
 image: mariadb:11.2.2
 environment:
 MARIADB_ROOT_PASSWORD:
root
 ports:
 - 3032:3306
 networks:
 - notes
 volumes:
 - ./db:/var/lib/mysql
networks:
 notes: {}

 

 

FE 컨테이너화

Dockerfile 작성

FROM node:18
WORKDIR /var/app
RUN npm install -g serve
COPY build ./build
EXPOSE 3000
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]

 

yaml 파일 작성

services:
 frontend:
 image: (...)
 environment:
 REACT_APP_API_BASE_URL: http://localhost:3031
 ports:
 - 3000:3000
 networks:
 - notes
(...)
networks:
 notes: {}