I’m trying to write a test for a function in my Node.js/Express application using Vitest. The function generateData processes some request data, calls two other functions (getParsedData and getRefactoredData), and sends a JSON response. I want to mock these two side effect functions to isolate the unit test for generateData.
Here’s the generateData function:
const generateData = catchAsync(
async (req: Request, res: Response, next: NextFunction) => {
const parsedData = await getParsedData(req.body);
const refactoredData = getRefactoredData(parsedData);
res.status(200).json(refactoredData);
}
);
This is my test:
import { describe, expect, it, vi } from "vitest";
import { createMocks } from "node-mocks-http";
import { Request, Response, NextFunction } from "express";
import {
generateData,
} from "../../src/handlers/resume.handler";
import * as resumeHandler from "../../src/handlers/resume.handler";
describe("generateData", () => {
it("should respond with resume data", async () => {
const mockNext = vi.fn();
const { req, res } = createMocks<Request, Response>({
method: "POST",
body: mockRawData,
});
const spyGetParsedData = vi.spyOn(resumeHandler,"getParsedData").mockReturnValue(mockParsedData);
const spyGetRefactoredData = vi.spyOn(resumeHandler,"getRefactoredData").mockReturnValue(mockRefactoredData);
await resumeHandler.generateData(req, res, mockNext);
expect(spyGetParsedData).toHaveBeenCalledWith(mockRawData);
expect(spyGetRefactoredData).toHaveBeenCalledWith(mockParsedData);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toEqual(mockRefactoredData);
spyGetParsedData.mockRestore();
spyGetRefactoredData.mockRestore();
});
});
However, I’m encountering an issue with the test. When I run it, I get the following error:
AssertionError: expected "getParsedData" to be called with arguments: [ Array(1) ]
Received:
Number of calls: 0
❯ test/handlers/resume.handler.test.ts:108:30
106| await resumeHandler.generateData(req, res, mockNext);
107|
108| expect(spyGetParsedData).toHaveBeenCalledWith(mockRawData);
| ^
109| expect(spyGetRefactoredData).toHaveBeenCalledWith(mockParsedData);
When I remove the spies and run the test below, it succeeds:
describe("generateData", () => {
it("should respond with resume data", async () => {
const mockNext = vi.fn();
const { req, res } = createMocks<Request, Response>({
method: "POST",
body: mockRawData,
});
await resumeHandler.generateData(req, res, mockNext);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toEqual(mockRefactoredData);
});
});