I've tried to create a class to connect to a mongoDB (and get a gridFS connection using (gridfs-stream
). But with that I do get two problems:
- I do get sometimes the mongo Error
server instance in invalid state connected
- It is impossible for me to mock this class out - using jestJS
So I would be very thankful if someone can help me to optimize this class to get a really solid working class. For example I don't like the let that = this
in the connect() function.
DB class
const mongo = require('mongodb')
const Grid = require('gridfs-stream')
const { promisify } = require('util')
export default class Db {
constructor (uri, callback) {
this.db = null
this.gfs = null
const server = process.env.MONGO_SERVER || 'localhost'
const port = process.env.MONGO_PORT || 27017
const db = process.env.MONGO_DB || 'test'
// Is this the correct way to connect (using mongo native driver)?
this.connection = new mongo.Db(db, new mongo.Server(server, port))
this.connection.open = promisify(this.connection.open)
this.connected = false
return this
}
async connect (msg) {
let that = this
if (!this.db) {
try {
await that.connection.open()
that.gfs = Grid(that.connection, mongo)
this.connected = true
} catch (err) {
console.error('mongo connection error', err)
}
}
return this
}
isConnected () {
return this.connected
}
}
Example
This function will add a new user to the DB using the class above:
import bcrypt from 'bcrypt'
import Db from './lib/db'
const db = new Db()
export async function createUser (obj, { username, password }) {
if (!db.isConnected()) await db.connect()
const Users = db.connection.collection('users')
return Users.insert({
username,
password: bcrypt.hashSync(password, 10),
createdAt: new Date()
})
}
Unit test
I need to create a unit test to test if the mongoDB method is called. No integration test for testing the method. So I need to mock the DB connection, collection and insert method.
import bcrypt from 'bcrypt'
import { createUser } from '../../user'
import Db from '../../lib/db'
const db = new Db()
jest.mock('bcrypt')
describe('createUser()', () => {
test('should call mongoDB insert()', async () => {
bcrypt.hashSync = jest.fn(() => SAMPLE.BCRYPT)
// create somekind of mock for the insert method...
db.usersInsert = jest.fn(() => Promise.resolve({ _id: '507f1f77bcf86cd799439011' }))
await createUser({}, {
username: 'username',
password: 'password'
}).then((res) => {
// test if mocked insert method has been called
expect(db.usersInsert).toHaveBeenCalled()
// ... or better test for the returned promise value
})
})
})