I am building a full stack application with NextJS and a MySQL database.In my API routes I make calls to this database (for example, createOne()
for creating an instance in the database). When I run my tests using jest, I want to mock this call, so that the actual createOne() does not run, but only test so that it is called. From what I've understood this is possible using mocks, but my tests still runs using the real function.
lib/database.js
const createConnection = async () => {}; // creates the connection
export const createOne = async (instance) => {}; // inserts the instance to the database
pages/api/index.js
import { createOne } from 'lib/database';
const handler = () => {
... // validation, creating the instance to insert etc.
const id = await createOne(instance); // <-- this I don't want to be run when testing
res.status(201).json({id, ...instance});
};
export default handler();
__tests__/api/index.js
import handler from 'pages/api/index';
import { createOne } from 'lib/database';
// I struggle how to structure the mock implementation here
beforeAll(() => {
const createOne = jest.fn(); // ?
});
...
test(async () => {
... // setup req, res object
await handler(req, res);
// I have tests for the API logic, but it currently calls the database every time, which I don't want to.
expect(createOne.mocks.calls.length).toBe(1); // here I get 0
});
I don't really know where I'm doing it wrong, and I have been searching around a lot but most examples are just mocking modules such as axios
etc.
You don't seem to be mocking the function...
See below and see if it works...
// mock function
const createOneMock = jest.fn().mockImplementation(async (val) => 1)
// Mock the module
jest.mock("../lib/database", () => {
return createOneMock
})
const handler = require("../index")
test('my test', async () => {
var req = {}
var res = {}
const rc = await handler(req, res);
expect(rc).toBe(1)
expect(createOneMock.mock.calls.length).toBe(1)
})
ps: I'm using Node to test this, but the concept should be the same regardless if you are using node or not.
The way I got it working is some workarounds needed for jest to mock esModules. See below a working example:
import handler from 'src/pages/api/index';
import { createOne } from 'src/lib/database';
jest.mock('src/lib/database', () => ({
__esModule: true,
createOne: jest.fn().mockImplementation(async (val) => 1)
}));
test('it calls the mock and returns id: 1', async () => {
const { req, res } = mockReqRes(); // using node-mocks-http, out of scope
await handler(req, res);
expect(createOne.mock.calls.length).toEqual(1);
expect(res._getJSONData()).toEqual(
expect.objectContaining({
id: 1
})
);
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.