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
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.
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.
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.
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.
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"
.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With