Издевательская модель Mongoose со шуткой

Я пытаюсь издеваться над моделью mongoose со jest, но получает Cannot create property 'constructor' on number '1' ошибке Cannot create property 'constructor' on number '1'. Я смог воспроизвести проблему, создав проект с двумя файлами, показанными ниже. Есть ли способ издеваться над моделью мангуста со 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 = () => {
//   ...
// }

Ошибка:

 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)

Обновить:

Кажется, это ошибка в шутку. https://github.com/facebook/jest/issues/3073

Ответ 1

Хорошо, у меня была та же проблема, поэтому я создаю этот пакет, чтобы решить эту проблему: https://www.npmjs.com/package/mockingoose

вот как вы можете использовать это, скажем, это ваша модель:

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);

и это ваш тест:

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

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

проверьте папку с тестами для получения дополнительных примеров: https://github.com/alonronin/mockingoose/blob/master/___tests___/index.test.js

нет соединений с базой данных!

Ответ 2

Другим решением является spyOn функций prototype модели.

Например, это приведет к сбою MyModel.save():

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

Вы можете использовать mockImplementationOnce чтобы не иметь необходимость в mockRestore шпиона. Но вы также можете использовать mockImplementation и использовать что-то вроде:

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

Протестировано с помощью "mongoose": "^4.11.7" и "jest": "^23.6.0".

Ответ 3

Mockingoose, кажется, очень хорошее решение. Но я также смог смоделировать свою модель с Jest.mock() функции Jest.mock(). По крайней мере, create метод.

// in the module under the test I am creating (saving) DeviceLocation to DB
// someBackendModule.js
...
DeviceLocation.create(location, (err) => {
...
});
...

Определение модели DeviceLocation:

// DeviceLocation.js
import mongoose from 'mongoose';

const { Schema } = mongoose;
const modelName = 'deviceLocation';

const DeviceLocation = new Schema({
...
});

export default mongoose.model(modelName, DeviceLocation, modelName);

Макет DeviceLocation в папке __mocks__ в той же папке, что и модель DeviceLocation:

// __mock__/DeviceLocation.js
export default {
    create: (x) => {    
        return x;
    },
};

в тестовом файле:

// test.js
// calling the mock
...
jest.mock('../../src/models/mongoose/DeviceLocation');
import someBackendModule from 'someBackendModule';
...
// perform the test