Skip to content

Latest commit

 

History

History
89 lines (61 loc) · 3.1 KB

testing-express-with-mongodb.md

File metadata and controls

89 lines (61 loc) · 3.1 KB

Testing REST API with MongoDB

To write API tests for an Express app that uses MongoDB as the database, we are going to use a library called mongodb-memory-server. It spins up an in-memory instance of MongoDB, which is faster than running a separate MongoDB instance.

The library helps to give us a clean/empty database for each test case, so that the test cases do not interfere with each other (e.g. if a test case fail and leave some garbage data in its copy of database, that failure will not affect other test cases because each test case starts with a clean database).

Here is an example on using it with Jest: https://github.com/nodkz/mongodb-memory-server#simple-jest-test-example

Adding tests to the Books API

In this example, we'll be adding tests to the express-books-api.

Install the testing libraries as dev dependencies:

npm install --save-dev jest supertest mongodb-memory-server

Create an app.test.js file and initialize Mongodb Memory Server:

// app.test.js
const express = require("express");
const request = require("supertest");

// Initialize MongoDB Memory Server
const MongodbMemoryServer = require("mongodb-memory-server").default;
const mongod = new MongodbMemoryServer();
const mongoose = require("mongoose");
const Author = require("./models/author");

const app = require("./app");

async function addFakeAuthors() {
  const author1 = new Author({
    name: "paulo",
    age: 49
  });

  await author1.save();

  const author2 = new Author({
    name: "john",
    age: 50
  });

  await author2.save();
}

beforeAll(async () => {
  // Increase timeout to allow MongoDB Memory Server to be donwloaded
  // the first time
  jest.setTimeout(120000);

  const uri = await mongod.getConnectionString();
  await mongoose.connect(uri);
});

afterAll(() => {
  mongoose.disconnect();
  mongod.stop();
});

beforeEach(async () => {
  // Clean DB between test runs
  mongoose.connection.db.dropDatabase();

  // Add fake data to the DB to be used in the tests
  await addFakeAuthors();
});

test("GET /authors", async () => {
  const response = await request(app).get("/authors");

  expect(response.status).toBe(200);

  // Assert based on the fake data added
  expect(response.body.length).toBe(2);
});

Each test should be independent of the others - importantly, the order in which the tests run shouldn't affect whether they pass or fail.

Another strategy for doing integration testing with database

In the example above, we make use of the mongodb-memory-server to automatically give us a fresh database in each test case.

Without that library, another possible solution is to explicitly delete all data in the test database after each test finishes running. That's a bit tedious but still works. Here is a sample project showing this approach. Checkout the test cases in tests/integration-tests to see the sample tests.