I am working in a test module for my application which uses Sequelize to make queries to a database. I am trying to mock this module and I found this answer which was oriented to typescript: How to mock Sequelize with Jest?
I am doing my test in javascript and I find the mocked function isn't working. So I would like to find an alternative to call the function member of a mocked module inside a test block and perform an implementation of it. I'm not sure if it is a good practice, but I didn't find another way to test the procedure, so I require to reimplement the member definition, however when I run the test, it appears as the reimplementation wasn't performed.
The function I was intended to test is in file sql-api.js
const initDB = async function () {
await connect()
await synchronizePatients()
};
const sequelize = new Sequelize(config.db.database, config.db.username, config.db.password, {
host: config.db.host,
dialect: 'postgres'
});
const connect = async function () {
try {
return await sequelize.authenticate();
} catch (error) {
console.error('Unable to connect to the database:', error);
return error;
}
}
const synchronizePatients = async function () {
console.log("Synchronize patients")
return await Patients.sync({ alter: true })
}
const Patients = sequelize.define('patients', {
uuid: {
primaryKey: true,
allowNull: false,
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4 // Or Sequelize.UUIDV1
},
id: {
type: DataTypes.INTEGER,
},
nombres: {
type: DataTypes.STRING,
allowNull: false
},
apellidos: {
type: DataTypes.STRING,
allowNull: false
}, {
// Other model options go here
timestamps: true,
});
Then I have a mock module in __mock__
folder, named sequelized.js
'use strict';
const sequelize = jest.createMockFromModule('sequelize');
const mSequelize = {
authenticate: jest.fn(),
define: jest.fn()
};
const actualSequelize = jest.requireActual('sequelize');
sequelize.Sequelize = jest.fn(() => mSequelize);
sequelize.DataTypes = actualSequelize.DataTypes;
module.exports= sequelize;
Then in my test code in __tests__
folder:
const sqlapi = require("../sql-api");
const { Sequelize, Op } = require('sequelize');
const config = require("../config.json")
const mPatients = { sync: jest.fn() };
const mUsers = {
sync: jest.fn(),
findOne: jest.fn(),
create: jest.fn()
};
jest.mock("sequelize");
const mSequelizeContext = new Sequelize();
describe("Testing setup DB", () => {
afterAll(() => {
jest.resetAllMocks();
});
test("It should connect correctly", async () => {
mSequelizeContext.define.mockImplementation((modelName) => {
switch (modelName) {
case 'patients':
return mPatients;
case 'users':
return mUsers;
}
})
await sqlapi.initDB();
expect(Sequelize).toBeCalledWith(config.db.database, config.db.username, config.db.password, {
host: config.db.host,
dialect: 'postgres'
});
expect(mSequelizeContext.authenticate).toBeCalled();
})
})
However, when I try to run the code, I have the following error:
TypeError: Cannot read property 'sync' of undefined
374 | const synchronizePatients = async function () {
375 | console.log("Synchronize patients")
> 376 | return await Patients.sync({ alter: true })
| ^
377 | }
As the function define wasn't reimplemented in mSequelizeContext.define.mockImplementation(...)
. I don't know why it doesn't work. In the example I referred first, to call the mocked function they use a mocked(mSequelizeContext.define)
, however, that mocked
function is part of another library ts-jest/utils
oriented to typescript. I was wondering that in Javascript it isn't needed.
I also noticed that replacing the implementation in the mock folder by:
const mSequelize = {
authenticate: jest.fn(),
define: jest.fn().mockImplementation((modelName) => {
switch (modelName) {
case 'patients':
return mPatients;
case 'users':
return mUsers;
}
})
};
And here it works, but by the other way, reimplementing inside the test procedure, it doesn't.
Please, if you could orient me in this implementation.
question from:
https://stackoverflow.com/questions/65914016/how-can-i-reimplement-a-mock-function-of-a-manually-mocked-module