javascriptnode.jsunit-testingtddkoa

How do I mock my config file for testing?


I have a Koa app I just started and I need to test something that grabs data from a config file.

I need to test with specific data, but I'm not sure how to modify what data the test receives from the config file.

Example:

app.js

var router = require('koa-router');
var config = require('./config.js');
var db     = require('./db.js');
var auth   = require('./auth');
var app    = require('koa')();

router.get('/', function *() {
  if(auth(this.req, config.credentials.secret)) { // Authenticates request based on a hash created using a shared secret
    this.body = "Request has been authenticated";
  }
});

app.use(router.routes());
app = module.exports = http.createServer(app.callback());

app.listen(3000);

appSpec.js

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

describe('app', function() {
  it('should authenticate all requests against config shared secret', function() {
    var secret    = 'some_secret';
    var validHash = /* hash created from test secret and query */;

    request(app)
      .get('/')
      .query({query: 'some_query'})
      .query({hash: validHash})
      .expect(403, done);

  });
});

This spec will fail because the app will use the secret from the config file(empty string) instead of my test secret.


Solution

  • Alright, I played around with some different ways to handle this.

    The best option I found, for my particular use case, was proxyquire. It's an npm package that lets you override dependencies in any file that you require in your test suites.

    So if I am testing this module:

    ./controllers/myController.js

    var config = require('../config.js');
    
    module.exports = function() {
     // Do some stuff
    };
    

    I would do something like this:

    ./test/controllers/myControllerSpec.js

    var proxyquire = require('proxyquire');
    var config = {
      credentials: {
        secret: 'my_secret'
      }
      // other fake config stuff
    };
    var myController = proxyquire('../../controllers/myController.js', {'../config.js', config});
    
    describe('myController', function() {
      // TESTS
    });
    

    and this instance of myController will use my test config.

    This won't work for end to end testing, unless the only place you import your config is the main app file.