【问题标题】:How to mock mongodb manager in typescript using jest如何使用 jest 在 typescript 中模拟 mongodb 管理器
【发布时间】:2021-09-01 20:17:56
【问题描述】:

如何返回一个 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();

【问题讨论】:

    标签: typescript unit-testing jestjs mocking ts-jest


    【解决方案1】:

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

    您可以将间谍添加到 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.
    

    【讨论】:

      猜你喜欢
      • 2022-12-09
      • 2018-07-23
      • 2020-03-18
      • 1970-01-01
      • 2019-08-11
      • 1970-01-01
      • 2021-01-13
      • 2021-09-11
      • 1970-01-01
      相关资源
      最近更新 更多