2025년 2월 5일

김동환·2025년 2월 5일
0

TIL (Today I Learned) - NestJS 댓글 컨트롤러 유닛 테스트

NestJS에서 CommentsController 유닛 테스트 작성

오늘은 NestJS의 댓글 컨트롤러(CommentsController)에 대한 유닛 테스트를 작성하는 방법을 학습했다.
NestJS에서 컨트롤러의 동작을 검증하기 위해 @nestjs/testing 패키지를 활용하여 테스트 모듈을 생성하고,
가짜(Mock) 서비스 객체를 주입하는 방식으로 테스트를 진행했다.


🔹 1. 테스트를 위한 기본 설정

describe 블록과 beforeEach 설정

  • describe를 사용하여 "댓글 컨트롤러(CommentsController)"에 대한 테스트 블록을 만들었다.
  • beforeEach에서 Test.createTestingModule()을 사용하여 테스트 모듈을 설정하고,
    • CommentsController를 컨트롤러로 등록하고,
    • CommentsService가짜(mock) 객체useValue로 주입했다.
  • JwtAuthGuard를 우회하기 위해 overrideGuard(JwtAuthGuard).useValue({ canActivate: () => true })를 사용하여 인증을 무시했다.

🔹 2. 컨트롤러 기본 정의 테스트

it('컨트롤러가 정의되어 있어야 한다.', () => {
  expect(controller).toBeDefined();
});
  • 컨트롤러가 정상적으로 생성되었는지 확인하는 기본 테스트이다.

🔹 3. 댓글 생성 API 테스트

describe('댓글 생성', () => {
  it('새로운 댓글을 생성해야 한다.', async () => {
    const dto: CreateCommentDto = { content: '새 댓글' };
    const result = { id: 1, cardId: 1, userId: 1, content: '새 댓글' };

    mockCommentsService.createComment.mockResolvedValue(result);

    expect(await controller.createComment({ user: { id: 1 } }, 1, dto)).toEqual({ data: result });

    expect(service.createComment).toHaveBeenCalledWith(1, 1, '새 댓글');
  });
});
  • 댓글 생성 API(/comments)의 동작을 검증하는 테스트이다.
  • mockCommentsService.createComment가 정상적으로 호출되고, 예상된 값이 반환되는지 확인했다.

🔹 4. 특정 카드의 댓글 목록 조회 API 테스트

describe('카드별 댓글 조회', () => {
  it('카드에 달린 모든 댓글을 반환해야 한다.', async () => {
    const result = [{ id: 1, cardId: 1, content: '테스트 댓글' }];

    mockCommentsService.getCommentByCardId.mockResolvedValue(result);

    expect(await controller.findAllComment(1)).toEqual({ data: result });

    expect(service.getCommentByCardId).toHaveBeenCalledWith(1);
  });
});
  • 특정 카드에 달린 모든 댓글을 가져오는 API(/comments/card/:cardId)를 테스트했다.
  • getCommentByCardId가 올바르게 호출되었는지 검증했다.

🔹 5. 특정 ID의 댓글 조회 API 테스트

describe('댓글 단건 조회', () => {
  it('특정 ID의 댓글을 반환해야 한다.', async () => {
    const result = { id: 1, cardId: 1, content: '테스트 댓글' };

    mockCommentsService.getCommentById.mockResolvedValue(result);

    expect(await controller.findOneComment(1)).toEqual(result);

    expect(service.getCommentById).toHaveBeenCalledWith(1);
  });
});
  • 특정 ID의 댓글을 조회하는 API(/comments/:id)의 동작을 검증했다.

🔹 6. 댓글 수정 API 테스트

describe('댓글 수정', () => {
  it('댓글을 수정해야 한다.', async () => {
    const dto: UpdateCommentDto = { content: '수정된 댓글' };
    const result = { id: 1, userId: 1, content: '수정된 댓글' };

    mockCommentsService.updateComment.mockResolvedValue(result);

    expect(await controller.updateComment({ user: { id: 1 } }, 1, dto)).toEqual({ data: result });

    expect(service.updateComment).toHaveBeenCalledWith(1, 1, '수정된 댓글');
  });
});
  • 댓글 수정 API(/comments/:id)의 동작을 검증했다.
  • updateComment가 올바른 인자로 호출되는지 확인했다.

🔹 7. 댓글 삭제 API 테스트

describe('댓글 삭제', () => {
  it('댓글을 삭제해야 한다.', async () => {
    const result = { id: 1, userId: 1, deleted: true };

    mockCommentsService.deleteComment.mockResolvedValue(result);

    expect(await controller.deleteComment({ user: { id: 1 } }, 1)).toEqual({ data: result });

    expect(service.deleteComment).toHaveBeenCalledWith(1, 1);
  });
});
  • 댓글 삭제 API(/comments/:id)의 동작을 검증했다.
  • deleteComment가 예상대로 호출되었는지 확인했다.

배운 점

  1. NestJS의 @nestjs/testing을 사용하여 테스트 모듈을 구성하는 방법을 익혔다.
  2. 서비스(Mock Service)를 주입하여 컨트롤러의 유닛 테스트를 작성하는 방법을 학습했다.
  3. jest.fn()을 사용하여 Mock 객체의 동작을 설정하는 방법을 배웠다.
  4. 각 API의 요청 및 응답을 검증하는 테스트 코드 작성 방법을 연습했다.
  5. overrideGuard(JwtAuthGuard)를 사용하여 인증을 우회하는 방법을 활용했다.

느낀 점

NestJS에서 컨트롤러 테스트를 작성하면서 jest@nestjs/testing을 활용한 Mock 객체 생성 및 주입이 핵심이라는 점을 깨달았다.
또한 beforeEach를 사용해 반복적인 설정을 줄일 수 있었고, 개별 API 테스트에서 서비스 메서드가 올바르게 호출되는지 확인하는 과정이 중요하다는 것도 배웠다.

다음에는 E2E 테스트도 함께 진행하여 API의 전체적인 동작을 검증하는 방법을 연습해보고 싶다!

profile
Node.js 7기

0개의 댓글

관련 채용 정보