'Nextjs Api unit test - difficult to mock prisma client
I am stuck since long as it is kind of difficult to mock DB calls in unit testing in Nextjs. I have used @prisma/client for database communication. I have studied https://www.prisma.io/docs/guides/testing/unit-testing but this the issue is doc have just used simple method and they pass the ctx to it if I do so then the actual api call will not understand what is ctx.user.create is?
Here is my adduser.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient();
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
try {
const user = await prisma.user.create({data: req.body});
const user = await ctx.prisma.user.create({data: req.body});
res.status(200).send(user);
// if I send ctx here then the actual call will not communicate with db
// const user = await ctx.prisma.user.create({data: req.body});
} catch (e: unknown) {
const message = e.message;
res.status(500).send({ message });
}
} else {
return res.status(404).json({ message: 'Request not found!' });
}
}
Now what is the way to mock this prisma.user.create()???? What I have tried I will share but different ways have different issues just checkout how I have tried
//adduser.test.ts
import adduser from "../../pages/api/addUser";
const { MockContext, Context, createMockContext } = require('../../utils/context')
let mockCtx: MockContext;
let ctx: Context;
describe("Test auth api", () => {
beforeEach(async () => {
mockCtx = createMockContext()
ctx = mockCtx as unknown as Context
});
it("should return 200 and correct response", async () => {
let req:any = {
body: {
id: "7e36e11e-ad4d-4504-9262-e2b95378cf00",
first_name: "Temp",
last_name: "temp",
account_address: "0x5eb128b7f43ee7768e4ddd7476a5c60bdb971111",
email: "[email protected]",
twitter_handle: "temp_twitter",
discord_handle: "temp_discord"
}
}
req.method = "POST";
const json = jest.fn();
const status = jest.fn(()=>{
return {
json
}
});
const res = {
status
}
// with context
mockCtx.prisma.user.create.mockResolvedValue(req.body);
const response = await adduser(req, res, ctx);
expect(true).toBe(true);
expect(res.status).toHaveBeenCalledWith(200);
// expect(response.body).toHaveProperty("first_name");
});
});
//adduser.test.ts
import http from 'http';
import supertest from "supertest";
const { apiResolver } = require('next/dist/server/api-utils');
// const prisma = require('../../client')
import { MockContext, Context, createMockContext } from '../../utils/context'
import adduser from "../../pages/api/addUser";
import { prismaMock } from '../../singleton';
let mockCtx: MockContext
let ctx: Context
const tempUser = {
id: "7e36e11e-ad4d-4504-9262-e2b95378cf00",
first_name: "Temp",
last_name: "temp",
account_address: "0x5eb128b7f43ee7768e4ddd7476a5c60bdb971111",
email: "[email protected]",
twitter_handle: "temp_twitter",
discord_handle: "temp_discord"
}
describe("Test auth api", () => {
let server;
beforeEach(async () => {
const requestHandle = (request, response) =>
apiResolver(
request,
response,
undefined,
adduser,
{},
true,
);
server = http.createServer(requestHandle);
mockCtx = createMockContext()
ctx = mockCtx as unknown as Context
});
afterEach(() => {
server.close();
});
it("should return 200 and correct response", async () => {
// const body = {
// reqUser: tempUser,
// ctx
// }
// without context
prismaMock.user.create.mockResolvedValue(tempUser)
// with context
// mockCtx.prisma.user.create.mockResolvedValue(tempUser);
const response = await supertest(server).post("/api/adduser").send(tempUser);
expect(response.statusCode).toBe(200);
expect(response.body).toHaveProperty("first_name");
});
});
Kindly guide me for the solution for mocking db calls in unit testing in the nextjs handler/api
Solution 1:[1]
Since the method you are testing is a Next.js API route, you won't be able to pass your own context as another parameter which means you can't go the dependency injection route for mocking the Prisma Client.
Try following the singleton pattern in the unit testing docs you have linked above. Make sure you don't miss the "Prerequisites" section where you add singleton.ts
to your setupFilesAfterEnv
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Austin Crim |