如何使用 jest 在打字稿中模拟 mongodb 经理

How to mock mongodb manager in typescript using jest

如何 return 一个 mongodb.connection.db() 类型的值并模拟它的集合? 我创建了一个 mongoClient 类型的连接并使用了它的 db() 函数。如果一切正常,我输入这个的集合信息,但我无法编写测试,因为我无法模拟它。

dbManager.ts

import { MongoClient } from 'mongodb';

class DBManager {
  private connection?: MongoClient;
  private mongoUrl = null;

  constructor(url: string) {
    this.mongoUrl = url;
  }

  get db() {
    return this.connection!.db();
  }

  async start() {
    if (!this.connection) {
      this.connection = await MongoClient.connect(this.mongoUrl);
    }
  }
}

export default DBManager;

index.ts

 const dbManager = new DBManager(url);
  await dbManager.start();
  const db = dbManager.db;

  if (db) {
    const collection = db.collection(collectionName);
  }

index.spec.ts

  const dbManager = new DBManager( 'mongoUrl');
      jest.spyOn(dbManager, 'start').mockResolvedValue();
      jest.spyOn(dbManager, 'db', 'get').mockImplementation();

mock不成功的原因是你在测试用例中新建了一个DBManager 实例,而jest.spyOn()只对这个实例的方法添加了spy。在测试代​​码中是 DBManager 的另一个实例,仍然调用其原始的 unspy 方法。

您可以将间谍添加到 DBManager.prototype.start()DBManager.prototype.get() 方法。

此外,不要忘记在 afterEach 钩子中将模拟恢复到它们的原始值。保证测试用例的mock对象不会影响其他测试用例。

例如

DBManager.ts:

import { MongoClient } from 'mongodb';

class DBManager {
  private connection?: MongoClient;
  private mongoUrl: string = '';

  constructor(url: string) {
    this.mongoUrl = url;
  }

  get db() {
    return this.connection!.db();
  }

  async start() {
    if (!this.connection) {
      this.connection = await MongoClient.connect(this.mongoUrl);
    }
  }
}

export default DBManager;

index.ts:

import DBManager from './dbManager';

export async function main() {
  const url = 'mongodb://localhost:27017';
  const collectionName = 'user';
  const dbManager = new DBManager(url);
  await dbManager.start();
  const db = dbManager.db;

  if (db) {
    const collection = db.collection(collectionName);
  }
}

index.test.ts:

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

describe('69011729', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  test('should pass', async () => {
    const mDB = ({
      collection: jest.fn(),
    } as unknown) as Db;
    jest.spyOn(DBManager.prototype, 'start').mockResolvedValue();
    jest.spyOn(DBManager.prototype, 'db', 'get').mockReturnValueOnce(mDB);
    await main();
    expect(DBManager.prototype.start).toBeCalledTimes(1);
    expect(mDB.collection).toBeCalledWith('user');
  });

  test('should restore original methods', () => {
    expect(jest.isMockFunction(DBManager.prototype.start)).toBeFalsy();
  });
});

测试结果:

 PASS  examples/69011729/index.test.ts (10.734 s)
  69011729
    ✓ should pass (4 ms)
    ✓ should restore original methods

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        11.516 s
Ran all test suites related to changed files.