When working with NestJS it can sometimes be difficult to figure out how to write tests around the dependency injection system. In searching for how I could write unit tests for services when using Prisma I found a lot of wild and hacky workarounds. But by consulting Prisma documentation I found a very simple, and clean answer.
First thing, let's say we have this code that creates a new user. You'll notice we're using dependency injection to bring in a PrismaService which connects to the database.
1constructor(private readonly prisma: PrismaService) {}
2
3async create(
4 data: CreateOneUserArgs,
5 select?: Prisma.UserSelect
6): Promise<Partial<User>> {
7 return this.prisma.user.create({
8 ...data,
9 select,
10 });
11}
First we need to follow the Prisma documentation to create mock objects. Most importantly for our case is creating the singleton.ts file.
1import { PrismaClient } from '@prisma/client'
2import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
3
4import prisma from './client';
5
6jest.mock('./client', () => ({
7 __esModule: true,
8 default: mockDeep<PrismaClient>(),
9}))
10
11beforeEach(() => {
12 mockReset(prismaMock)
13})
14
15export const prismaMock = prisma as unknown as DeepMockProxy<PrismaClient>
We can then use the exported prismaMock as a provider in our unit test.
1let service: UserService;
2
3beforeEach(async () => {
4 const module: TestingModule = await Test.createTestingModule({
5 providers: [
6 UserService,
7 { provide: PrismaService, useValue: prismaMock },
8 ],
9 }).compile();
10
11 service = module.get<UserService>(UserService);
12});
Then just return to the Prisma documentation to keep following their example to write a test for creating a new user with the singleton method.
1test('should create new user ', async () => {
2 const user = {
3 id: 1,
4 name: 'Jill',
5 email: 'hello@example.com',
6 acceptTermsAndConditions: true,
7 }
8
9 prismaMock.user.create.mockResolvedValue(user)
10
11 await expect(service.create(user)).resolves.toEqual({
12 id: 1,
13 name: 'Jill',
14 email: 'hello@example.com',
15 })
16})