jofftiquez
jofftiquez

Reputation: 7708

Mocha how to expose a node controller function to test script

Here is my foo-controller.js.

module.exports = function(params) {

    var router = require('express').Router();
    var db = params.db
    var controller = {};

    controller.getFoo = function (req, res) {
        // returns something
    }

    router.get('/foo', controller.getFoo);

    return router;

};

and here is my test.js.

var chai = require('chai');
var expect = require('chai').expect;
var bar = require('../api/controllers/bar/foo-controller');

console.log("Test", bar) // <- this returns the whole foo-controlelr.js

describe('Foo', function() {
    it('should blah blah', function() {

    });
});

But every time I to use bar.getFoo() <- the function I wanted to test. It returns the error has no method 'getFoo'

Upvotes: 1

Views: 1131

Answers (1)

saintedlama
saintedlama

Reputation: 6898

Accessing the controller's getFoo function would require you to export this function via module.exports. But the code above does not export the controller but the router which is perfectly fine since the router is used to mount the router in express.

For testing your controller you might split routing/route definition and controller in it's own modules:

foo-controller.js

module.exports = function(params) {
  var db = params.db
  var controller = {};

  controller.getFoo = function (req, res) {
    // returns something
  }
  return controller;

};

foo-router.js

var fooController = require('./foo-controller');

module.exports = function(params) {

  var router = require('express').Router();

  var controller = fooController(params);

  router.get('/foo', controller.getFoo);

  return router;
};

This enables you to test the controller without the router.

Another approach to test the code could be to do an "integration" test, testing the router and the controller together. Using a tool like supertest (https://github.com/visionmedia/supertest) you can write your integration test just like:

var request = require('supertest');
var express = require('express');
var fooRouter = require('.path/to/router/foo');

describe('Foo', function() {
  it('should blah blah', function(done) {

    var app = express();

    app.use('/', fooRouter(params));

    request(app)
      .get('/foo')
      .expect(200)
      .end(function(err, res){
        if (err) throw err;
        done();
      });
    });
  });
});

The advantage of this approach is that your testing route definition plus controller.

Upvotes: 1

Related Questions