최근에 나는 Nest.js를 사용하여 간단한 서비스를 개발하는 중이다 이 프로젝트에서 중요한 것 중 하나는 테스트 주도 개발(TDD)을 통해 안정적이고 신뢰성 있는 코드를 작성하는 것인데. 이 블로그 포스트에서는 Nest.js의 BlogService 클래스에 대한 TDD 개발 과정을 공유하고자 한다.
import { Injectable, Param } from '@nestjs/common';
import { Blog } from './blog.schema';
interface BlogInterface {
getAllPosts(): Promise<Blog[]>;
createPost(post: any): Blog;
updatePost(id: string, post: any): Blog;
deletePost(id: string): void;
getPost(id: string): Promise<Blog>;
}
@Injectable()
export class BlogService implements BlogInterface {
getAllPosts(): Promise<Blog[]> {
throw new Error('Method not implemented.');
}
createPost(post: any): Blog {
throw new Error('Method not implemented.');
}
updatePost(id: string, post: any): Blog {
throw new Error('Method not implemented.');
}
deletePost(id: string): void {
throw new Error('Method not implemented.');
}
getPost(id: string): Promise<Blog> {
throw new Error('Method not implemented.');
}
}
import { Test, TestingModule } from '@nestjs/testing';
import { BlogService } from './blog.service';
import { Blog } from './blog.schema';
describe('BlogService', () => {
let service: BlogService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [BlogService],
}).compile();
service = module.get<BlogService>(BlogService);
});
const postData = {
id: '1',
title: '블로그 제목',
content: '블로그 내용.',
name: 'json lee',
};
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('getAllPosts', () => {
it('모든 posts 정보를 가져온다', async () => {
// Arrange
const mockPosts = [{ ...postData }];
jest.spyOn(service, 'getAllPosts').mockResolvedValue(mockPosts);
// Act
const result = await service.getAllPosts();
// Assert
expect(result).toEqual(mockPosts);
});
});
describe('createPost', () => {
it('포스트 하나를 등록한다', () => {
jest.spyOn(service, 'createPost').mockReturnValue(postData);
const result = service.createPost(postData);
expect(result).toEqual(postData);
});
});
describe('updatePost', () => {
it('포스트를 업데이트한다 ', () => {
const id = '1';
const expectedResult = postData;
jest.spyOn(service, 'updatePost').mockReturnValue(postData);
const result = service.updatePost(id, postData);
expect(result).toEqual(expectedResult);
});
});
describe('deletePost', () => {
it('포스트 하나를 삭제한다 ', () => {
const id = '1'; // Mock the id
jest.spyOn(service, 'deletePost').mockImplementation(() => {});
expect(() => service.deletePost(id)).not.toThrow();
});
});
describe('getPost', () => {
it('포스트 id를 전달받아 post 정보를 가져온다 ', async () => {
const id = '1'; // Mock the id
const expectedResult = postData; // Mock the expected result
jest.spyOn(service, 'getPost').mockResolvedValue(postData);
const result = await service.getPost(id);
expect(result).toEqual(expectedResult);
});
});
});

import { Model } from 'mongoose';
import { PostDto } from './blog.model';
import { Blog, BlogDocument } from './blog.schema';
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
export interface BlogRepository {
getAllPost(): Promise<PostDto[]>;
createPost(postDto: PostDto);
getPost(id: String): Promise<PostDto>;
deletePost(id: String);
updatePost(id: String, postDto: PostDto);
}
@Injectable()
export class BlogMongoRepository implements BlogRepository {
constructor(@InjectModel(Blog.name) private blogModel: Model<BlogDocument>) {}
async getAllPost(): Promise<Blog[]> {
return await this.blogModel.find().exec();
}
async createPost(postDto: PostDto) {
const createPost = {
...postDto,
createdDt: new Date(),
updatedDt: new Date(),
};
this.blogModel.create(createPost);
}
async getPost(id: string): Promise<PostDto> {
return await this.blogModel.findById(id);
}
async deletePost(id: string) {
await this.blogModel.findByIdAndDelete(id);
}
async updatePost(id: string, postDto: PostDto) {
const updatePost = { id, ...postDto, updatedDt: new Date() };
await this.blogModel.findByIdAndUpdate(id, updatePost);
}
}
import { Injectable, Param } from '@nestjs/common';
import { Blog } from './blog.schema';
import { BlogRepository } from './blog.repository';
import { PostDto } from './blog.model';
interface BlogInterface {
getAllPosts(): Promise<Blog[]>;
createPost(post: PostDto): Blog;
updatePost(id: string, post: PostDto): Blog;
deletePost(id: string): void;
getPost(id: string): Promise<Blog>;
}
@Injectable()
export class BlogService implements BlogInterface {
constructor(private readonly blogRepository: BlogRepository) {}
deletePost(id: string): void {
throw new Error('Method not implemented.');
}
async getAllPosts() {
return await this.blogRepository.getAllPosts();
}
createPost(postDto: PostDto): Blog {
return this.blogRepository.createPost(postDto);
}
async getPost(id): Promise<PostDto> {
return await this.blogRepository.getPost(id);
}
delete(id): void {
this.blogRepository.deletePost(id);
}
updatePost(id, postDto: PostDto) {
return this.blogRepository.updatePost(id, postDto);
}
}