How can I return a mongodb.connection.db() type value and mock its collection? I create a mongoClient type connection and use its db() function. If all works work correctly, I enter the collection information of this but i couldn't write test of it because i can't mock it.
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();
The reason why the mock is not successful is that you created a new DBManager
instance in the test case, and jest.spyOn()
only adds spy to the method of this instance. In the tested code is another instance of DBManager
, still calling its original, unspy method.
You can add spy to DBManager.prototype.start()
and DBManager.prototype.get()
methods.
Besides, don't forget to restore mocks back to their original value in afterEach
hook. To ensure that the mock object of the test case will not affect other test cases.
E.g.
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();
});
});
test result:
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.