如何用 Jest 模拟 MongoDB ( mongoClient )

How To Mock MongoDB ( mongoClient ) With Jest

我有一个 DBManager class 连接到 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();

我这样称呼它 class

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

当我尝试模拟时出现此错误:

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

这是我使用的 mock 方法:

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

谢谢..

您可以使用 jest.spyOn(object, methodName, accessType?) 模拟 DBManager.start() 方法和 DBMananger.connection getter。

例如

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

测试结果:

 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