오늘은 NestJS의 댓글 컨트롤러(CommentsController)에 대한 유닛 테스트를 작성하는 방법을 학습했다.
NestJS에서 컨트롤러의 동작을 검증하기 위해 @nestjs/testing
패키지를 활용하여 테스트 모듈을 생성하고,
가짜(Mock) 서비스 객체를 주입하는 방식으로 테스트를 진행했다.
describe
블록과 beforeEach
설정describe
를 사용하여 "댓글 컨트롤러(CommentsController)"에 대한 테스트 블록을 만들었다.beforeEach
에서 Test.createTestingModule()
을 사용하여 테스트 모듈을 설정하고,CommentsController
를 컨트롤러로 등록하고,CommentsService
의 가짜(mock) 객체를 useValue
로 주입했다.JwtAuthGuard
를 우회하기 위해 overrideGuard(JwtAuthGuard).useValue({ canActivate: () => true })
를 사용하여 인증을 무시했다.it('컨트롤러가 정의되어 있어야 한다.', () => {
expect(controller).toBeDefined();
});
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, '새 댓글');
});
});
/comments
)의 동작을 검증하는 테스트이다.mockCommentsService.createComment
가 정상적으로 호출되고, 예상된 값이 반환되는지 확인했다.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);
});
});
/comments/card/:cardId
)를 테스트했다.getCommentByCardId
가 올바르게 호출되었는지 검증했다.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);
});
});
/comments/:id
)의 동작을 검증했다.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, '수정된 댓글');
});
});
/comments/:id
)의 동작을 검증했다.updateComment
가 올바른 인자로 호출되는지 확인했다.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);
});
});
/comments/:id
)의 동작을 검증했다.deleteComment
가 예상대로 호출되었는지 확인했다.@nestjs/testing
을 사용하여 테스트 모듈을 구성하는 방법을 익혔다.jest.fn()
을 사용하여 Mock 객체의 동작을 설정하는 방법을 배웠다.overrideGuard(JwtAuthGuard)
를 사용하여 인증을 우회하는 방법을 활용했다.NestJS에서 컨트롤러 테스트를 작성하면서 jest
와 @nestjs/testing
을 활용한 Mock 객체 생성 및 주입이 핵심이라는 점을 깨달았다.
또한 beforeEach
를 사용해 반복적인 설정을 줄일 수 있었고, 개별 API 테스트에서 서비스 메서드가 올바르게 호출되는지 확인하는 과정이 중요하다는 것도 배웠다.
다음에는 E2E 테스트도 함께 진행하여 API의 전체적인 동작을 검증하는 방법을 연습해보고 싶다!