노드심화 5-6

·2022년 12월 29일
0

study

목록 보기
46/78
post-thumbnail

Repository Layer 단위 테스트 (UnitTest)

Repository의 경우 연결되어 있는 하위 계층은 DB뿐!

Repository의 단위 테스트(UnitTest)를 구현하기 위해 DB에 접근하여 실제 데이터를 건드리지 않도록 DB를 Mocking하도록 하겠습니다.

  1. __tests__ 폴더 하위에 unit폴더를 생성하고, posts.repository.unit.spec.js 파일을 만들기
  2. PostRepository 클래스의 단위 테스트 코드는 findAllPost, createPost 2개의 Method를 구현
  3. mockPostsModel이라는 실제 DB를 Mocking하기 위한 Mock 객체를 생성
    => jest.fn()사용해서 Method Mocking
  4. Mock Function을 이용해 PostRepository 클래스의 단위 테스트 코드를 구현

Mock Function

특정 Method가 몇번 호출되었는지, 어떤 값으로 호출되었는지 확인하고 싶거나 Mocking한 Method의 Return 값을 임의로 설정하고 싶을 때 해당하는 문법을 사용하여 설정할 수 있습니다.

// findAll Mock 함수를 실행했을 때, 결과값이 정상적으로 반영되었는지 확인합니다.
expect(findAllResultValue).toBe("Return Value");

// findAll Mock 함수가 몇번 호출했는지 확인합니다.
expect(findAll).toHaveBeenCalledTimes(1);

posts.repository.unit.spec.js

// __tests__/unit/posts.repository.unit.spec.js

const PostRepository = require("../../repositories/posts.repository");

//mocking을 할 떄 사용하는 객체
// posts.repository.js 에서는 아래 5개의 Method만을 사용합니다.
let mockPostsModel = {
  findAll: jest.fn(),
  findByPk: jest.fn(),
  create: jest.fn(),
  update: jest.fn(),
  destroy: jest.fn(),
};

let postRepository = new PostRepository(mockPostsModel);

//테스트 코드생성
describe("Layered Architecture Pattern Posts Repository Unit Test", () => {
  // 각 test가 실행되기 전에 실행됩니다.
  beforeEach(() => {
    jest.resetAllMocks(); // 모든 Mock을 초기화합니다.
  });

  test("Posts Repository findAllPost Method", async () => {
    mockPostsModel.findAll = jest.fn(() => {
      return "findAll Result"; //findAllPost 메소드가 실행되면 return
    });

    const posts = await postRepository.findAllPost();

    // postsModel에 있는 findAll Method는 한 번만 실행된다.
    expect(mockPostsModel.findAll).toHaveBeenCalledTimes(1);

    // postsModel에 있는 findAll Method의 결과값이 바로 return 되어야 한다.
    expect(posts).toEqual("findAll Result");
  });

  test("Posts Repository createPost Method", async () => {
    mockPostsModel.create = jest.fn(() => {
      return "create Result";
    });

    const createPostParams = {
      nickname: "createPostNickname",
      password: "createPostPassword",
      title: "createPostTitle",
      content: "createPostContent",
    };

    const createPostData = await postRepository.createPost(
      createPostParams.nickname,
      createPostParams.password,
      createPostParams.title,
      createPostParams.content
    );

    //1. 할당이 제대로 됐는지 => postsModel.create Method의 결과가 createPostData와 일치
    expect(createPostData).toEqual("create Result");
    //2. 한 번 호출
    expect(mockPostsModel.create).toHaveBeenCalledTimes(1);
    //3. 어떤 방식으로 어떤 값이 호출되는지 검증=> {nickname, password, title, content}
    expect(mockPostsModel.create).toHaveBeenCalledWith({
      nickname: createPostParams.nickname,
      password: createPostParams.password,
      title: createPostParams.title,
      content: createPostParams.content,
    });
  });
});

Repository Layer가 사용하는 DB를 Mocking하여 실제 DB에 접근하지 않도록 테스트 코드를 작성하였고, 성공 케이스의 단위 테스트를 구현할 수 있게 되었습니다! 😁

profile
개발자 꿈나무

0개의 댓글