Jest 模拟 MongoDB 的嵌套函数

Swa*_*nil 1 mocking mongodb node.js jestjs

我有一个管理 MongoDB 客户端方法的帮助程序类。

class Common {
   constructor() {
        this._client = null;
   }
   
   static async connect(url) {
        this._client = await MongoClient.connect(url, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
        });
        return this._client;
    }

    static async getCollection({ url, db_name, collection_name }) {
        const client = await Common.connect(url);

        return client.db(db_name).collection(collection_name);
    }
   
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试为 getCollection 方法编写测试用例。这就是我尝试过的

jest.mock('mongodb');
it('To check if the collection method on the MongoClient instance was invoked', () => {
    Common.getCollection({});

    const mockMongoClientInstance = MongoClient.mock.instances[0];
    const mockMongoDBConnect = mockMongoClientInstance.connect;
    expect(mockMongoDBConnect).toHaveBeenCalledTimes(1);
});
Run Code Online (Sandbox Code Playgroud)

显然,这个测试用例覆盖了getCollection方法的第一行,并且测试用例实际上尝试执行第二行。我如何模拟第二行?任何建议都会有帮助。提前致谢。

sli*_*wp2 7

您可以使用jest.spyOn(object, methodName)来模拟Common.connect()MongoClient.connect()方法。

\n

例如

\n

common.js:

\n
import { MongoClient } from \'mongodb\';\n\nexport class Common {\n  constructor() {\n    this._client = null;\n  }\n\n  static async connect(url) {\n    this._client = await MongoClient.connect(url, {\n      useNewUrlParser: true,\n      useUnifiedTopology: true,\n    });\n    return this._client;\n  }\n\n  static async getCollection({ url, db_name, collection_name }) {\n    const client = await Common.connect(url);\n\n    return client.db(db_name).collection(collection_name);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

common.test.js:

\n
import { Common } from \'./common\';\nimport { MongoClient } from \'mongodb\';\n\ndescribe(\'66848944\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  describe(\'#getCollection\', () => {\n    it(\'To check if the collection method on the MongoClient instance was invoked\', async () => {\n      const client = { db: jest.fn().mockReturnThis(), collection: jest.fn() };\n      const connectSpy = jest.spyOn(Common, \'connect\').mockResolvedValueOnce(client);\n      await Common.getCollection({ url: \'mongodb://localhost:27017\', db_name: \'awesome\', collection_name: \'products\' });\n      expect(connectSpy).toBeCalledWith(\'mongodb://localhost:27017\');\n      expect(client.db).toBeCalledWith(\'awesome\');\n      expect(client.collection).toBeCalledWith(\'products\');\n    });\n  });\n\n  describe(\'#connect\', () => {\n    it(\'should connect to mongo db\', async () => {\n      const connectSpy = jest.spyOn(MongoClient, \'connect\').mockReturnValueOnce({});\n      const actual = await Common.connect(\'mongodb://localhost:27017\');\n      expect(actual).toEqual({});\n      expect(connectSpy).toBeCalledWith(\'mongodb://localhost:27017\', {\n        useNewUrlParser: true,\n        useUnifiedTopology: true,\n      });\n    });\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

单元测试结果:

\n
 PASS  examples/66848944/common.test.js\n  66848944\n    #getCollection\n      \xe2\x9c\x93 To check if the collection method on the MongoClient instance was invoked (5 ms)\n    #connect\n      \xe2\x9c\x93 should connect to mongo db (1 ms)\n\n-----------|---------|----------|---------|---------|-------------------\nFile       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n-----------|---------|----------|---------|---------|-------------------\nAll files  |   85.71 |      100 |   66.67 |   85.71 |                   \n common.js |   85.71 |      100 |   66.67 |   85.71 | 5                 \n-----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        5.165 s, estimated 6 s\n
Run Code Online (Sandbox Code Playgroud)\n