Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocha + Nodejs + Heroku .env file

I have a REST app written in NodeJS running on Heroku. I have my .env file setup for local development and works fine whenever I run foreman to serve my app locally. The app also runs fine when I deploy it to my heroku server.

I am trying to write unit tests for my app with Mocha/Supertest/should/assert. When I run my app through Mocha, it doesn't load up the .env file to get my environment variables – in my case, the URL for the PSQL database. As a result, all my tests that involve DB I/O timeout.

I've been scouring the Internet for a solution but I can't seem to find anything helpful.

Here is some sample code:

app.js:

var application_root = __dirname,
    express          = require("express"),
    port             = process.env.PORT || 4482;
    pg               = require('pg').native,
    client           = new pg.Client(process.env.DATABASE_URL);

// Connect To DB
client.connect();

(...)

app.get('/api', function (req, res) {
  res.send('PS API is running');
});
app.get('/', function (req, res) {
  res.send('PS API is running');
});

(...)

// Read Users
app.get('/users', function (req,res) {
    user.readUsers(res,client);
});

(...)

// Launch server
console.log('Listening on port: '+ port);
app.listen(port);
module.exports = app;

userTest.js

var request = require('supertest');
var assert  = require('assert');
var app     = require('app.js');
var should  = require('should');

describe('Get /', function(){
    it('should respond OK',function(done){
        request(app)
        .get('/')
        .end(function(err, res){
          res.status.should.equal(200);
          done(err);
        });
    });
});

describe('Get /api', function(){
    it('should respond OK',function(done){
        request(app)
        .get('/api')
        .end(function(err, res){
          res.status.should.equal(200);
          done(err);
        });
    });
});

// Getting All Users
describe('Get /users', function(){
    it('should respond OK',function(done){
        request(app)
        .get('/users')
        .end(function(err, res){
          res.status.should.equal(200);
          done(err);
        });
    });
});

.env

== LOCAL DB ==
DATABASE_URL=MY_DB_URL
HEROKU_POSTGRESQL_GOLD_URL=MY_DB_URL
PATH=bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin

And the output I get from running mocha test

Listening on port: 4482

  ․․Getting all users
․

  2 passing (2 seconds)
  1 failing

  1) Get /users should respond OK:
     Error: timeout of 2000ms exceeded
      at Object.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:165:14)
      at Timer.list.ontimeout (timers.js:101:19)

When I replace the process.env.DATABASE_URL with my hardcoded PSQL local URL, the tests all pass. So it's clear that the .env file is not being read by mocha.

I have also tried passing env vars to Mocha with little success. Does anyone know of a proper way to have Mocha read in my environment vars from the .env file?

like image 290
Gimli Avatar asked Jun 27 '13 21:06

Gimli


2 Answers

The foreman gem (written by a Heroku engineer, to make it easy to use .env files and Procfiles in development as you would on Heroku production) has a command just for this purpose: run.

foreman run npm test <-- or however you trigger your tests.

Alternatively, on my current project here's what we do:

  • we have a test.env file containing the environmental variables and values appropriate for testing, in Unix export format. So, yes, export DATABASE_URL=MY_DB_URL. The format is a bit different, but that's an annoyance we're OK with
  • We have a Makefile containing the following directives:
-include test.env

test:
    npm test

When we want to run the tests for our project we just make test. Make will load up the test.env file, assign all the environmental variables, then run npm test for us.

like image 125
RyanWilcox Avatar answered Nov 08 '22 05:11

RyanWilcox


I'm not entirely sure, but I don't think you can make mocha read your .env file. That appears to be specific to foreman. If your environment variable definitions are plain KEY=VALUE, then I believe something as simple as env $(cat .env) mocha would do. Otherwise, you may have to do some preprocessing first using sed/perl/etc.

like image 36
happppy_user Avatar answered Nov 08 '22 07:11

happppy_user