Integration testing in a Mongoose world

Integration testing in a Mongoose world

by John Vincent


Posted on April 21, 2017


Integration Testing with Fake Data

Take the restaurants app and implement Integration Tests using a faked database. Setup continuous integration with Travis and deploy to Heroku.

From Thinkful course Node 2.3.1.

Final Result

My Git repository

Deployed to Heroku

Test GET at Heroku

Getting Started

Clone repository

cd MyDevelopment/github-clones

git clone https://github.com/Thinkful-Ed/node-restaurants-app-mongoose node-restaurants-app-mongoose-ci

cd node-restaurants-app-mongoose-ci

git checkout -b feature/with-tests origin/feature/with-tests
git fetch

Create Github repository node-restaurants-app-mongoose-ci

Copy source files from:

MyDevelopment/github-clones/node-restaurants-app-mongoose-ci

to:

MyDevelopment/github/thinkful/node-restaurants-app-mongoose-ci

Commit to repository

cd MyDevelopment/github/thinkful
create-repo node-restaurants-app-mongoose-ci

Install dependencies

npm install

To run the tests

npm test

Construct and Test with Fake Data

Use package Faker

const faker = require('faker');

Add mongo database for testing in config.js

exports.TEST_DATABASE_URL = (
    process.env.TEST_DATABASE_URL ||
    'mongodb://localhost/test-restaurants-app');

Reference the database

const {TEST_DATABASE_URL} = require('../config');

Create the fake data

function seedRestaurantData() {
  console.info('seeding restaurant data');
  const seedData = [];

  for (let i=1; i<=10; i++) {
    seedData.push(generateRestaurantData());
  }
  // this will return a promise
  return Restaurant.insertMany(seedData);
}

// used to generate data to put in db
function generateBoroughName() {
  const boroughs = [
    'Manhattan', 'Queens', 'Brooklyn', 'Bronx', 'Staten Island'];
  return boroughs[Math.floor(Math.random() * boroughs.length)];
}

// used to generate data to put in db
function generateCuisineType() {
  const cuisines = ['Italian', 'Thai', 'Colombian'];
  return cuisines[Math.floor(Math.random() * cuisines.length)];
}

// used to generate data to put in db
function generateGrade() {
  const grades = ['A', 'B', 'C', 'D', 'F'];
  const grade = grades[Math.floor(Math.random() * grades.length)];
  return {
    date: faker.date.past(),
    grade: grade
  }
}

// generate an object represnting a restaurant.
// can be used to generate seed data for db
// or request.body data
function generateRestaurantData() {
  return {
    name: faker.company.companyName(),
    borough: generateBoroughName(),
    cuisine: generateCuisineType(),
    address: {
      building: faker.address.streetAddress(),
      street: faker.address.streetName(),
      zipcode: faker.address.zipCode()
    },
    grades: [generateGrade(), generateGrade(), generateGrade()]
  }
}

Tear down the Database after each test

function tearDownDb() {
    console.warn('Deleting database');
    return mongoose.connection.dropDatabase();
}

For each test:

describe('Restaurants API resource', function() {

  // we need each of these hook functions to return a promise
  // otherwise we'd need to call a `done` callback. `runServer`,
  // `seedRestaurantData` and `tearDownDb` each return a promise,
  // so we return the value returned by these function calls.
  before(function() {
    return runServer(TEST_DATABASE_URL);
  });

  beforeEach(function() {
    return seedRestaurantData();
  });

  afterEach(function() {
    return tearDownDb();
  });

  after(function() {
    return closeServer();
  })

Configure Travis CI

edit .travis.yml

language: node_js
node_js: node
services:
- mongodb

Git commit but do not push

git add .
git commit -m "travis"

Add Travis CI Service in Github

https://github.com/johnvincentio/node-restaurants-app-mongoose-ci
Settings, Integration & Services
Add service, Travis CI
Add Service (green button at bottom)

Configure Travis

Travis Dashboard
https://travis-ci.org/

click icon (top-right)

Sync Account (top-right)

Check:
johnvincentio/node-restaurants-app-mongoose-ci

Git commit to remote

git push

Verify Building

Travis Dashboard
https://travis-ci.org/

Select:
johnvincentio/node-restaurants-app-mongoose-ci

Deploy to Heroku

Login to Travis CI

cd MyDevelopment/github/thinkful/node-restaurants-app-mongoose-ci

travis login --auto-password

To deploy to Heroku:

travis setup heroku
    "return" to the questions.

git diff (see differences)
    note deploy block added to .travis.yml

Create app on Heroku

heroku create

Notice:

calm-harbor-24855
https://calm-harbor-24855.herokuapp.com/
https://git.heroku.com/calm-harbor-24855.git

Push to Heroku:

git push heroku master

Start up a dyno:

heroku ps:scale web=1

Edit .travis.yml

deploy:
    app: calm-harbor-24855

Git commit changes to master

MongoDB, Mongoose, mLab, and Heroku

At mLab, create new database: node-restaurants-app-mongoose-ci

mongo ds151018.mlab.com:51018/node-restaurants-app-mongoose-ci -u <dbuser> -p <dbpassword>

mongodb://<dbuser>:<dbpassword>@ds151018.mlab.com:51018/node-restaurants-app-mongoose-ci

Create user: jvtest

Import data

cd /Users/jv/Desktop/MyDevelopment/github/thinkful/node-restaurants-app-mongoose-ci/data

mongoimport --db node-restaurants-app-mongoose-ci --collection restaurants --drop --file primer-dataset.json --host ds151018.mlab.com --port 51018  -u jvtest -p <password>

Connect

mongo ds151018.mlab.com:51018/node-restaurants-app-mongoose-ci -u jvtest -p <password>
use node-restaurants-app-mongoose-ci
db.restaurants.find()

Connect using Studio3T

  • Start Studio3T
  • New Connection
Server
Name: ds151018.mlab.com
Type: Direct Connection
Server: ds151018.mlab.com
Port: 51018

Authentication, Standard
User name: jvtest
DB: node-restaurants-app-mongoose-ci

Server
Test Connection

OK>

Connect

will find node-restaurants-app-mongoose-ci etc

Select Connection (left menu), right click, IntelliShell

use node-restaurants-app-mongoose-ci
db.restaurants.findOne()

Configure Heroku

From the Heroku dashboard

select: calm-harbor-24855

Settings, Reveal Config Vars

Key: DATABASE_URL

Value:
mongodb://jvtest:<password>@ds151018.mlab.com:51018/node-restaurants-app-mongoose-ci

Test Heroku App

Open App, adding /restaurants (to test)

https://calm-harbor-24855.herokuapp.com/restaurants

should retrieve some restaurants data

End