[js]unit test를 위한 테스트 데이터 생성하기

SYhwang·2023년 3월 5일
0

jest와 supertest를 이용해 유닛 테스트를 위한 코드를 작성하는 도중, 처음에는 DB에 들어있던 더미 데이터를 dump해서 테스트 DB에 넣어둔 상태로 테스트를 진행하였다.

그러나 테스트 DB는 다른 테스트나 실제 데이터에 영향을 미치지 않도록 매번 테스트를 진행할 때마다 테스트용 데이터를 넣었다가, 테스트가 끝나면 테스트 데이터를 삭제하도록 코드를 작성해야 한다는 피드백을 받았고 다음과 같은 방법으로 코드를 개선하였다.

// tests/comment.test.js

const request = require("supertest");
const { createApp } = require("../app");
const { appDataSource } = require("../models/appDataSource");
const userFixture = require("./fixtures/user-fixtures");
const postFixture = require("./fixtures/post-fixtures");
const testUserData = require("./data/users");
const testPostData = require("./data/posts");

describe("COMMENT TEST", () => {
  let app;

  beforeAll(async () => {
    app = createApp();
    await appDataSource.initialize();
    await userFixture.createUsers(testUserData.users);
    await postFixture.createRoomStyles(testPostData.roomStyles);
    await postFixture.createPosts(testPostData.posts);
    await postFixture.createComments(testPostData.comments);
  });

  afterAll(async () => {
    await appDataSource.query(`SET FOREIGN_KEY_CHECKS = 0`);
    await appDataSource.query(`TRUNCATE comments`);
    await appDataSource.query(`TRUNCATE posts`);
    await appDataSource.query(`TRUNCATE room_styles`);
    await appDataSource.query(`TRUNCATE users`);
    await appDataSource.query(`SET FOREIGN_KEY_CHECKS = 1`);
    await appDataSource.query(`ALTER TABLE comments AUTO_INCREMENT = 1`);
    await appDataSource.destroy();
  });

  test("SUCCESS: GET COMMENTS BEFORE CREATING", async () => {
    const res = await request(app).get("/comments/post/1");

    expect(res.statusCode).toEqual(200);
    expect(res.body.data).toHaveLength(3);
    expect(res.body.data).toEqual(getComments);
  });

  test("SUCCESS: COMMENT CREATED", async () => {
    const res = await request(app)
      .post("/comments/post/1")
      .send({ userId: 1, content: "This is test comment" });

    expect(res.statusCode).toEqual(201);
    expect(res.body).toEqual({ message: "success" });
  });

  test("FAILED: CREATE COMMENT WITHOUT CONTENTS", async () => {
    const res = await request(app).post("/comments/post/1").send({ userId: 1 });

    expect(res.statusCode).toEqual(400);
    expect(res.body).toEqual({ message: "KEY_ERROR" });
  });

  test("SUCCESS: GET COMMENTS", async () => {
    const res = await request(app).get("/comments/post/1");

    expect(res.statusCode).toEqual(200);
    expect(res.body.data).toHaveLength(4);
    expect(res.body.data[0].content).toEqual("This is test comment");
  });

  test("SUCCESS: DELETE COMMENT", async () => {
    const res = await request(app).delete("/comments/4").send({ userId: 1 });

    expect(res.statusCode).toEqual(200);
    expect(res.body).toEqual({ message: "success" });
  });

  test("FAILED: DELETE COMMENT", async () => {
    const res = await request(app).delete("/comments/4").send({ userId: 1 });

    expect(res.statusCode).toEqual(400);
    expect(res.body).toEqual({ message: "DELETE FAILED" });
  });

  test("SUCCESS: GET COMMENTS", async () => {
    const res = await request(app).get("/comments/post/1");

    expect(res.statusCode).toEqual(200);
    expect(res.body.data).toHaveLength(3);
    expect(res.body.data).toEqual(getComments);
  });
});
  • 위와 같이 테스트 전에 user-fixtures 모듈을 호출해 모듈 내의 createdUsers() 함수를 사용한다.
  • createdUsers() 함수의 인자로는 data/users 파일을 호출해 파일 내의 users 배열을 사용했다.
    동일한 방식으로 댓글을 테스트할 때 필요한 데이터인 post와, post를 생성할 때 필요한 데이터인 room_styles도 생성하였다.
  • 데이터를 생성할 때 외래키를 고려하여 서로 영향을 받는 순서대로 생성하였다.
  • 테스트가 끝나면 테스트 데이터가 들어갔던 테이블들의 데이터를 전부 TRUNCATE 한다.
  • 테스트 데이터가 들어왔다가 지워지면 PK의 AUTO_INCREMENT 값이 변하므로, 필요한 경우 ALTER TABLE comments AUTO_INCREMENT = 1 처럼 다시 1로 세팅해 준다.
// tests/fixtures/user-fixtures.js

const { appDataSource } = require("../../models/appDataSource");

const createUsers = (userList) => {
  const data = [];

  for (const user of userList) {
    data.push([
      user.id,
      user.email,
      user.profile_image,
      user.password,
      user.nickname,
    ]);
  }

  return appDataSource.query(
    `
    INSERT INTO users (
      id,
      email,
      profile_image,
      password,
      nickname
    ) VALUES ?
  `,
    [data]
  );
};

module.exports = { createUsers };
  • user-fixtures에는 아래 users 같이 유저 정보 객체가 들어있는 배열을 인자로 받아 유저 정보 객체를 배열로 변환한 후 users 테이블에 insert into 하는 createUsers 함수를 작성하였다.
// tests/data/users.js

const users = [
  {
    id: 1,
    email: "test01@email.com",
    profile_image: "testProfileImage01.url",
    password: "password",
    nickname: "testUser01",
  },
  {
    id: 2,
    email: "test02@email.com",
    profile_image: "testProfileImage02.url",
    password: "password",
    nickname: "testUser02",
  },
  {
    id: 3,
    email: "test03@email.com",
    profile_image: "testProfileImage03.url",
    password: "password",
    nickname: "testUser03",
  },
];

module.exports = {
  users,
};
  • users 파일에서는 더미 데이터 하나하나를 객체로 만든 뒤 배열에 담아 users 라는 변수에 할당하였다.
  • DB에 이미 작성해둔 더미 데이터가 들어있었기에 해당 더미 데이터를 JSON 형태로 export해서 그대로 사용하였다.
  • id, created_at, updated_at 같이 원래는 자동으로 작성되는 column 이더라도 테스트시마다 변하지 않도록 하기 위해 모두 임의의 값을 넣어주는 것이 좋다고 한다.
  • 동일한 방식으로 post-fixures 파일과 data/posts 파일을 작성하였다.
  • 그리고 테스트를 돌려보면...

비어있는 테스트 DB에 데이터가 자동으로 들어갔다가 테스트가 정상적으로 실행된 뒤 전부 삭제된다!

0개의 댓글