node.jstypescriptunit-testingjestjsmocking

How to mock static method and their returned result in NodeJS + Typescript?


I am learning to write the unit test cases for NodeJS + Typescript using Jest. Currently, I have a very simple Express application, wherein the repository (that connects with MongoDB via a MongoConfig custom class) layer I have a few methods to insert/select the data. Below are two of them:

  export default class MyRepository {
    ...
    private _getCollection(collectionName: string): Collection {
      let collection = this._collections[collectionName];
      if (!collection) {
        collection = MongoConfig.getDatabase().collection(collectionName);
        this._collections[collectionName] = collection;
      }
      return collection;
    }

    public async insert(collectionName: string, dataToSave: any): Promise<void> {
      let collection = this._getCollection(collectionName);
      await collection.insertOne(dataToSave);
    }
    ...
  }

Here I want to mock MongoConfig.getDatabase().collection(<any string>) method call in _getCollection(..) method and return the mocked Collection object. How can this be achieved using Jest?

Also, it would be great if you could explain how we can test insert(..) method. Should we just check whether await collection.insertOne(dataToSave) is invoked in that method?


Solution

  • import { MongoConfig } from 'mongodb' // Substitute with the proper import
    
    const collectionMethods = {
      insertOne: jest.fn(async () => {})
    }
    const collection = jest.fn().mockReturnValue(collectionMethods);
    jest.spyOn(MongoConfig, 'getDatabase').mockReturnValue(collection);
    
    // Clear all mocks
    
    describe('insert', () => {
      it('works', async () => {
        const collectionName = 'foo';
        const dataToSave = {};
        const repo = new MyRepository();
        await repo.insert(collectionName, dataToSave);
        expect(collection).toHaveBeenCalledWith(collectionName);
        expect(collectionMethods.insertOne).toHaveBeenCalledWith(dataToSave);
      })
    })
    

    If you're going to repeat this pattern in multiple test files, consider creating a manual mock for your mongodb driver that exports the mock MongoConfig