How do I mock my config file for testing?
Asked Answered
F

3

15

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.

Fakery answered 11/2, 2016 at 21:14 Comment(0)
F
9

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.

Fakery answered 18/2, 2016 at 21:37 Comment(0)
E
7

I use node-config for my config files and configuration loading based on machine or env variable.

You can specify your config in a variety of formats (.json, .js, yaml, etc.) Using the default settings, you need to create a config folder in your app root and a default.<format> with your default config.

To override that for testing you can create a test.<format> file in your config directory. When you set your NODE_ENV=test, then node-config will see load your default config file and then it will load your test config file and if there are any conflicts for the values, your test config file will override the values in your default file.

Here are the full docs for setting up Configuration Files in node-config

Below is an example using node-config with a .js config file format.

./config/default.js

module.exports = {
  credentials: {
    secret: ''
  }
}

./config/test.js

module.exports = {
  credentials: {
    secret: 'abcdef123456'
  }
}

app.js

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

var credentials = config.get('credentials');

router.get('/', function *() {
  if(auth(this.req, 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);
Enriqueenriqueta answered 11/2, 2016 at 21:42 Comment(1)
What about when you want to test with different values of your secret? For example, writing a test when secret is null?Downcomer
M
6

Jest has nice support for this case. In your test file, add

jest.mock('../config.js', () => ({ 
  credentials: {
    secret: 'my_secret'
  }
  // other fake config stuff 
}));
My answered 6/1, 2021 at 18:54 Comment(1)
Best answer, imo. This is idiomatic jest.Capitol

© 2022 - 2024 — McMap. All rights reserved.