Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking Mongoose model with jest

Tags:

I am trying to mock a mongoose model with jest, but is getting Cannot create property 'constructor' on number '1' error. I was able to reproduce the issue by creating the project with 2 files shown below. Is there a way to mock a mongoose model with jest?

./model.js

const mongoose = require('mongoose')
const Schema = mongoose.Schema

const schema = new Schema({
  name: String
})

module.exports = mongoose.model('Test', schema)

./model.test.js

jest.mock('./model')
const Test = require('./model')

// Test.findOne.mockImplementation = () => {
//   ...
// }

Error:

 FAIL  ./model.test.js
  ● Test suite failed to run

    TypeError: Cannot create property 'constructor' on number '1'

      at ModuleMockerClass._generateMock (../../jitta/sandbox/rest_api/node_modules/jest-mock/build/index.js:458:34)
      at Array.forEach (native)
      at Array.forEach (native)
      at Array.forEach (native)

Update:

Seems to be a bug in jest. https://github.com/facebook/jest/issues/3073

like image 554
harinsa Avatar asked Mar 06 '17 07:03

harinsa


People also ask

How do you mock a model in jest?

Mocking user modules​ For example, to mock a module called user in the models directory, create a file called user. js and put it in the models/__mocks__ directory. Note that the __mocks__ folder is case-sensitive, so naming the directory __MOCKS__ will break on some systems.

How do you mock a constructor in jest?

In order to mock a constructor function, the module factory must return a constructor function. In other words, the module factory must be a function that returns a function - a higher-order function (HOF). Since calls to jest. mock() are hoisted to the top of the file, Jest prevents access to out-of-scope variables.

How do you create mock data in testing jest?

In Jest, Node. js modules are automatically mocked in your tests when you place the mock files in a __mocks__ folder that's next to the node_modules folder. For example, if you a file called __mock__/fs. js , then every time the fs module is called in your test, Jest will automatically use the mocks.

What is jest spyOn?

Jest's spyOn method is used to spy on a method call on an object. It is also very beneficial in cases where the Jest mock module or mock function might not be the best tool for the job on hand. While writing unit tests you only test one particular unit of code, generally a function.


2 Answers

An other solution is to spyOn the model prototype functions.

For example, this will make MyModel.save() fail :

    jest.spyOn(MyModel.prototype, 'save')
      .mockImplementationOnce(() => Promise.reject('fail update'))

You can use mockImplementationOnce to not having to mockRestore the spy. But you can also use mockImplementation and use something like :

afterEach(() => {
  jest.restoreAllMocks()
})

Tested with "mongoose": "^4.11.7" and "jest": "^23.6.0".

like image 151
Stephane L Avatar answered Sep 16 '22 19:09

Stephane L


ok, i had the same problem so i author this package to solve this problem: https://www.npmjs.com/package/mockingoose

this is how you can use it let's say this is your model:

import mongoose from 'mongoose';
const { Schema } = mongoose;

const schema = Schema({
    name: String,
    email: String,
    created: { type: Date, default: Date.now }
})

export default mongoose.model('User', schema);

and this is your test:

it('should find', () => {
  mockingoose.User.toReturn({ name: 2 });

  return User
  .find()
  .where('name')
  .in([1])
  .then(result => {
    expect(result).toEqual({ name: 2 });
  })
});

checkout the tests folder for more examples: https://github.com/alonronin/mockingoose/blob/master/___tests___/index.test.js

no connections is made to the database!

like image 22
Alon Valadji Avatar answered Sep 18 '22 19:09

Alon Valadji