3

I have a DBManager class to connect to mongoClient

import { MongoClient } from 'mongodb';

class DBManager {
  private url = process.env.MONGODB_URL;

  private _connection: MongoClient;

  constructor() {
    this._connection = null;
  }
  get connection() {
    return this._connection;
  }

  async start() {
    if (!this._connection) {
      this._connection = await MongoClient.connect(this.url);
    }
  }
}

export default new DBManager();

and I call this class like this

await DBManager.start();
const db = DBManager.connection.db(); 

I get this error when I try to mock:

Received: [TypeError: db_manager_1.default.connection.db is not a function]

this is how to mock method i use:

  DBManager.start = jest.fn().mockResolvedValue(() => ({
      connection: jest.fn().mockReturnThis(),
      db: jest.fn().mockResolvedValue({success: true})
    }));

thanks..

2 Answers 2

3

You can use a real MongoDB server to use in tests with the package mongodb-memory-server.

So in your case, you just need to do:

import { MongoMemoryServer } from '../index';

describe('Single MongoMemoryServer', () => {
  let con;
  let mongoServer;

  beforeAll(async () => {
    mongoServer = await MongoMemoryServer.create();
    process.env.MONGODB_URL = mongoServer.getUri();
  });

  afterAll(async () => {
    if (con) {
      await con.close();
    }
    if (mongoServer) {
      await mongoServer.stop();
    }
  });

  it('DBManager connection', async () => {
    await DBManager.start();
    const db = DBManager.connection.db();
    // ...
});
Sign up to request clarification or add additional context in comments.

Comments

1

You can use jest.spyOn(object, methodName, accessType?) to mock DBManager.start() method and DBMananger.connection getter.

E.g.

dbManager.ts:

import { MongoClient } from 'mongodb';

class DBManager {
  private url = process.env.MONGODB_URL || '';

  private _connection: MongoClient | null;

  constructor() {
    this._connection = null;
  }
  get connection() {
    return this._connection;
  }

  async start() {
    if (!this._connection) {
      this._connection = await MongoClient.connect(this.url);
    }
  }
}

export default new DBManager();

main.ts:

import DBManager from './dbManager';

export async function main() {
  await DBManager.start();
  const db = DBManager.connection!.db();
  db.collection('users');
}

main.test.ts:

import { main } from './main';
import DBManager from './dbManager';
import { Db, MongoClient } from 'mongodb';

describe('68888424', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  test('should pass', async () => {
    const mockDbInstance = ({
      collection: jest.fn(),
    } as unknown) as Db;
    const mockDb = jest.fn(() => mockDbInstance);
    jest.spyOn(DBManager, 'start').mockResolvedValueOnce();
    jest.spyOn(DBManager, 'connection', 'get').mockReturnValue(({ db: mockDb } as unknown) as MongoClient);
    await main();
    expect(DBManager.start).toBeCalledTimes(1);
    expect(DBManager.connection!.db).toBeCalledTimes(1);
    expect(mockDbInstance.collection).toBeCalledWith('users');
  });
});

test result:

 PASS  examples/68888424/main.test.ts (8.621 s)
  68888424
    ✓ should pass (5 ms)

--------------|---------|----------|---------|---------|-------------------
File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------|---------|----------|---------|---------|-------------------
All files     |      75 |       50 |      50 |      75 |                   
 dbManager.ts |   57.14 |       50 |   33.33 |   57.14 | 12-17             
 main.ts      |     100 |      100 |     100 |     100 |                   
--------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.532 s

1 Comment

Thanks, @slideshowp working great How should I write a test when I change the getter function in DBManager like this? DBManager ``` get connection() { return this._connection!.db(); } ``` main.ts ``` import DBManager from './dbManager'; export async function main() { await DBManager.start(); const db = DBManager.connection; db.collection('users'); } ```

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.