Search code examples
node.jsunit-testingtestingjestjs

MongoParseError: URI does not have hostname, domain name and tld only when testing the methods


I am trying to test my MongoDB library. I want to verify if a variable is an instance of my library and if the method is called correctly. I am using jest to make my tests.

import { MongoLib } from '../index'

let database: any

beforeAll(() => {
  database = new MongoLib({
    hostname: 'localhost',
    database: 'test',
    password: encodeURI('password'),
    username: 'anothertest'
  })
})

afterAll(() => {
 database = null
})

describe('Initializing class', () => {
  test('isInstanceOf', () => {
    expect(database).toBeInstanceOf(MongoLib)
  })
})

describe('Methods#ToBeThruty', () => {
  test('getAllToBeThruty', async () => {
    try {
      const users = await database.getAll('users')
      expect(users).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })
  test('getToBeThruty', async () => {
    try {
      const user = await database.get('users', '60e13de94a37e1c6d0174749')
      expect(user).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })
  test('createToBeThruty', async () => {
      try {
      const user = await database.create('users', { user: 'hello', email: 'world' })
      expect(user).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })
  test('updateToBeThruty', async () => {
    try {
      const user = await database.update('users', '60e13de94a37e1c6d0174749', { user: 'world', email: 'hello' })
      expect(user).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })

  test('replaceToBeThruty', async () => {
    try {
      const user = await database.replace('users', '60e13de94a37e1c6d0174749', { user: 'world', email: 'hello' })
      expect(user).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })

  test('deleteToBeThruty', async () => {
    try {
      const user = await database.delete('users', '60e13de94a37e1c6d0174749')
      expect(user).toBeTruthy()
    } catch (error) {
      console.error(error)
    }
  })
})

The test is passing, but after that, I am getting this error:

MongoParseError: URI does not have hostname, domain name and tld at parseSrvConnectionString (/Users/diesanromero/Documents/KemusCorp/OpenSource/mongodb- crud/node_modules/mongodb/lib/core/uri_parser.js:51:21)

at MongoLib.Object..MongoLib.connect (/Users/diesanromero/Documents/KemusCorp/OpenSource/mongodb- crud/src/index.ts:25:29) at MongoLib. (/Users/diesanromero/Documents/KemusCorp/OpenSource/mongodb- crud/src/index.ts:40:17)

The code for MongoLib is the following:

import { MongoClient, ObjectId } from 'mongodb'
import Settigns from "./settings"

export class MongoLib {
  private credentials: string
  private database: string
  private host: string
  private options: object
  private client: MongoClient
  private url: string
  private static connection: any

  constructor(settings: Settigns) {
    this.credentials = `${settings.username}:${settings.password}`
    this.host = `${settings.hostname}:${settings.port}`
    this.database = settings.database

    this.url = `mongodb+srv://${this.credentials}@${this.host}/${settings.database}?retryWrites=true&w=majority`
    this.options = { useUnifiedTopology: true }
    this.client = new MongoClient(this.url, this.options)
  }

  private connect () {
    if (!MongoLib.connection) {
      MongoLib.connection = new Promise((resolve, reject) => {
        this.client.connect((error: Error) => {
          if (error) reject(error)
          else {
            resolve(this.client.db(this.database))
            console.log('Connected successfully to MongoDB.')
          }
        })
      })
    }

    return MongoLib.connection
  }
  
  public async getAll (collection: string, query?: object) {
    return this.connect()
      .then((db: any) => {
        return db.collection(collection).find(query).toArray()
      })
  }

  public async get (collection: string, id: string) {
    return this.connect()
      .then((db:any) => {
        return db.collection(collection).findOne({ _id: new ObjectId(id) })
      })
  }

  public async create (collection: string, data: object) {
    return this.connect()
      .then((db: any) => {
        return db.collection(collection).insertOne(data)
      })
      .then(() => 'Data inserted')
  }

  public async update (collection: string, id: string, data: object) {
    return this.connect()
      .then((db: any) => {
        return db.collection(collection).updateOne({ _id: new ObjectId(id) }, { $set: data }, { upsert: true })
      })
      .then(() => 'Data updated')
  }

  public async replace (collection: string, id: string, data: object) {
    return this.connect()
      .then((db: any) => {
        return db.collection(collection).replaceOne({ _id: new ObjectId(id) }, data, { upsert: true })
      })
      .then(() => 'Data replaced')
  }

  public async delete (collection: string, id: string) {
    return this.connect()
      .then((db: any) => {
        return db.collection(collection).deleteOne({ _id: new ObjectId(id) })
      })
      .then(() => 'Data deleted')
  }
}

Take in mind that settings.js is an exported interface with the basic configuration.


Solution

  • Make sure your connection string has following in the beginning.

    1. mongodb+srv://
    2. mongodb://

    Secondly check that if your password has anything for the below list then replace it from the following enter image description here

    3rd approach which worked for me is create a new user with the password which does not have any special character.