Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
259 views
in Technique[技术] by (71.8m points)

javascript - how can I reimplement a Mock function of a manually mocked module?

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...