Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock Mongoose 'find()' function in Jest?

I have a service:

export default class WorldService {

constructor(worldModel) {
    this.worldModel = worldModel;
  }

  async getWorlds() {
    let resData = {};
    await this.worldModel.find({}, (err, worlds) => {
      resData = worlds;
    });
    return resData;
  }
}

I have a Mongoose model:

import mongoose from 'mongoose';

const worldSchema = mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
});

export default mongoose.model('World', worldSchema);

I want to mock the Mongoose model and test the service function called getWorlds(). I am using Jest as a Testing Framework in my project.

I tried to write an unit test in Jest:

import WorldModel from '../../../src/models/world';
import WorldService from '../../../src/services/world';

describe('When data is valid', () => {
  beforeAll(() => {
    jest.spyOn(WorldModel, 'find').mockReturnValue(Promise.resolve([
      { _id: '5dbff32e367a343830cd2f49', name: 'Earth', __v: 0 },
      { _id: '5dbff89209dee20b18091ec3', name: 'Mars', __v: 0 },
    ]));
  });

  it('Should return entries', async () => {
    const worldService = new WorldService(WorldModel);

    const expected = [
      { _id: '5dbff32e367a343830cd2f49', name: 'Earth', __v: 0 },
      { _id: '5dbff89209dee20b18091ec3', name: 'Mars', __v: 0 },
    ];
    await expect(worldService.getWorlds()).resolves.toEqual(expected);
  });
});

I get a failing answer:

 FAIL  test/unit/services/world.test.js
  When data is valid
    × Should return entries (9ms)

  ● When data is valid › Should return entries

    expect(received).resolves.toEqual(expected) // deep equality

    Expected: [{"__v": 0, "_id": "5dbff32e367a343830cd2f49", "name": "Earth"}, {"__v": 0, "_id": "5dbff89209dee20b18091ec3", "name": "Mars"}]
    Received: {}

How to mock Mongoose find() function in Jest?

P.s. I prefer not to use any higher level test framework for MongoDB, e.g., mockgoose.

like image 540
Ugnius Malūkas Avatar asked Mar 04 '23 05:03

Ugnius Malūkas


1 Answers

You have problem in your service, if you use async await there is no need for callback:

export default class WorldService {
    constructor (worldModel) {
        this.worldModel = worldModel;
    }

    async getWorlds () {
        let resData = {};

        try {
            resData = await this.worldModel.find({});
        } catch (e) {
            console.log('Error occured in getWorlds', e);
        }

        return resData;
    }
}

I use this to mock mongoose model's find method:

describe('When data is valid', () => {
    beforeAll(() => {
        WorldModel.find = jest.fn().mockResolvedValue([{
                _id: '5dbff32e367a343830cd2f49',
                name: 'Earth',
                __v: 0
            },
            {
                _id: '5dbff89209dee20b18091ec3',
                name: 'Mars',
                __v: 0
            },
        ])
    });

    it('Should return entries', async () => {
        const worldService = new WorldService(WorldModel);

        const expected = [{
                _id: '5dbff32e367a343830cd2f49',
                name: 'Earth',
                __v: 0
            },
            {
                _id: '5dbff89209dee20b18091ec3',
                name: 'Mars',
                __v: 0
            },
        ];
        await expect(worldService.getWorlds()).resolves.toEqual(expected);
    });
});
like image 167
kaxi1993 Avatar answered Mar 05 '23 20:03

kaxi1993