https://mangkyu.tistory.com/143
단 통 시 인
https://github.com/Han9526/Node_Lv003-Architecture-
단위 테스트 직접해봄
import { prisma } from '../utils/prisma/index.js';
export class PostsRepository {
findAllPosts = async () => {
// ORM인 Prisma에서 Posts 모델의 findMany 메서드를 사용해 데이터를 요청합니다.
const posts = await prisma.posts.findMany();
return posts;
};
...
}
위와 같은 코드는 PostsRepository 가 findMany() 함수를 직접적으로 의존하고 있습니다
테스트 시에 실제 데이터베이스에 접근하여 테스트해야 하는 문제가 있습니다.
이를 해결하기 위해 모킹(Mocking)을 사용합니다
실제 데이터베이스에 접근하는 대신 가상의 데이터를 mocking 함수로 생성하여 테스트할 수 있습니다. 또한 모킹(Mocking)을 사용하면 코드를 격리시켜 독립적으로 실행 가능한 테스트를 보장할 수 있어서 단위 테스트(Unit Test)를 수행 할 때 사용합니다
먼저 의존성 주입(Dependency Injection)을 해야합니다
의존성을 주입하는 방법은 많지만 생성자(constructor)를 이용해 의존성 주입 작업을 하겠습니다
export class PostsRepository {
constructor(prisma) {
// 생성자에서 전달받은 Prisma 클라이언트의 의존성을 주입합니다.
this.prisma = prisma;
}
findAllPosts = async () => {
// ORM인 Prisma에서 Posts 모델의 findMany 메서드를 사용해 데이터를 요청합니다.
const posts = await this.prisma.posts.findMany();
return posts;
};
}
위와 같은 방법으로 아키텍쳐 3계층 controller,service,repository에 의존성 주입을 합니다
// 의존성주입
import { prisma } from '../utils/prisma/index.js';
import { PostsController } from '../controllers/posts.controller.js';
import { PostsService } from '../services/posts.service.js';
import { PostsRepository } from '../repositories/posts.repository.js';
import { UsersRepository } from '../repositories/users.repository.js';
// 의존성주입
const postsRepository = new PostsRepository(prisma);
const usersRepository = new UsersRepository(prisma);
const postsService = new PostsService(postsRepository, usersRepository);
const postsController = new PostsController(postsService);
이렇게 함으로써 각 계층에서 필요로 하는 데이터를 라우터에서 생성자를 통해 받아올 수 있게 되며, 이를 통해 의존성이 외부에서 주입되므로 각 계층은 외부 환경에 독립적으로 존재할 수 있습니다
위와 같은 방식으로 각 계층의 의존성을 주입했으니 이제 jest.js로 단위테스트를 진행
일단 findAllPosts만 테스트
// __tests__/unit/posts.repository.unit.spec.js
import { jest } from '@jest/globals';
import { PostsRepository } from '../../../src/repositories/posts.repository';
let mockPrisma = {
Posts: {
findMany: jest.fn(),
findUnique: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
},
Users: {},
};
let postsRepository = new PostsRepository(mockPrisma);
describe('Posts Repository Unit Test', () => {
// 각 test가 실행되기 전에 실행됩니다.
beforeEach(() => {
jest.resetAllMocks(); // 모든 Mock을 초기화합니다.
});
test('findAllPosts Method', async () => {
// findMany Mock의 Return 값을 "findMany String"으로 설정합니다.
const mockReturn = 'findMany String';
mockPrisma.Posts.findMany.mockReturnValue(mockReturn);
// postsRepository의 findAllPosts Method를 호출합니다.
const posts = await postsRepository.findAllPosts();
// prisma.posts의 findMany은 1번만 호출 되었습니다.
expect(postsRepository.prisma.Posts.findMany).toHaveBeenCalledTimes(1);
// mockPrisma의 Return과 출력된 findMany Method의 값이 일치하는지 비교합니다.
expect(posts).toBe(mockReturn);
});
});
터미널
PASS test/unit/repositories/posts.repositories.unit.spec.js
Posts Repository Unit Test
√ findAllPosts Method (4 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.669 s, estimated 1 s
Ran all test suites.