Skip to content

Using a different database for tests #138

@Wolemercy

Description

@Wolemercy

I'm trying to make use of an in-memory database (mongodb-memory-server) when running my tests, but I can't get it to work. I think that the fact that I'm requiring "loaders" when I create a server instance in the tests creates a mongoose connection with the actual database (mongoose.ts is one of the loaders). So I'm unable to connect with the test database.

I've gone through the "test-related" issues on this repo, and all of them seemed to make use of mocks, but I don't want to do that.

I'd appreciate any suggestions on how to resolve this---how to essentially, given this project structure, make use of a test database such as mongodb-memory-server.

Here's what my db-manager looks like - it houses the methods required to create the test DB.

import mongoose from "mongoose";
import { MongoMemoryServer }  from "mongodb-memory-server"

let mongod: MongoMemoryServer;

async function createMongoDB() {
  if (!mongod) {
    mongod = await MongoMemoryServer.create({
      binary: {
        version: "5.0.8"
      }
    })
  }
}

/**
 * Connect to the in-memory database.
 */
const connect = async () => {
  await createMongoDB()
  const uri = mongod.getUri()
  process.env.databaseURI = uri
  const connection = mongoose.connect(uri, { dbName: "riteshop-test-db"});
  return connection
}

/**
 * Clear the in-memory database.
 */
const clear = async () => {
  const collections = mongoose.connection.collections;
  for (const key in collections) {
    await collections[key].deleteMany({});
  }
};

/**
 * Disconnect from in-memory database.
 */
 const disconnect = async () => {
  await mongoose.connection.dropDatabase()
  await mongoose.connection.close()
  await mongod.stop()
}

export default { connect, clear, disconnect }

Also, here is what my test looks like

import request from "supertest"
import db from "../db-manager"
import config from "../../../src/config"
import express from "express"

describe("Health Check", () => {

  const app = express()
  beforeEach(async () => {
    await db.connect()
    // requiring the loaders is necessary because that's how the server is started normally
    // but that also means the db connection in `src/loaders/mongoose` would be initialized/attempted.
    // I don't want it attempted but it sorts of needs to be because the connection is needed by the dependency injector.
    await require("../../../src/loaders").default({ expressApp: app})
    app.listen(config.testPort)
  })
  
  afterEach(async () => {
    await db.clear()
    await db.disconnect()
  })
  
  describe('Endpoints availability', () => {
    it('should return 404', async () => {
      const res = await request(app).get('/api/nonexisting').send()
      expect(res.status).toEqual(404)
    })
  })

})

UPDATE: A few mins later

What I do now, which seems to work, is to

  • first, disconnect from the main db instance
  • then connect to the test db instance
const app = express()
  beforeEach(async () => {

    await require("../../../src/loaders").default({ expressApp: app})
    // disconecting from main DB
    mongoose.connection.close()
    // connecting to test DB
    await db.connect()
    app.listen(config.testPort)
  })

I'm hoping there's a much neater way to go about it. Furthermore, I'm not sure if this approach is consequence-free as the instance I had to disconnect from is what was passed to the dependencyInjectorLoader, and subsequently, the agendaInstance as seen in the repo's source code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions