Testing Mean.js Controllers – Part 2

You need to test that only authorized users can perform certain functions, to help prevent AshleyMadison-like embarrassments. Plus, doing so will boost your code coverage metrics by hitting all of those auth failure branches.

For mean.js with passport, you normally have something like this in each controller:

var users =  require(app/controllers/users/authorization.server.controller);

You need to mock this controller, using the method I described in another post on mocking. Yes, there are lots of mocking libraries available, but I’m too lazy to learn them, and so far, my cheap method seems to work really well for me.

var users =  require(config.requireModules.authorization.version);

In your normal config file, such as production.js, you would have:

requireModules: {
   authorization: {
      version: 'app/controllers/users/users.authorization.server.controller'
   }
 }

Note how the authorization.version field points to the normal auth controller.
In test.js, your config file for testing, you would include the following:

requireModules: {
   authorization: {
      version: 'app/tests/mock_modules/mock-users.authorization.server.controller'
   }
}

Now, you’ve successfully mocked your auth module. That module looks like this:

'use strict';

/**
 * Module dependencies.
 */
var passFailFlag = true;

//For test setup
exports.passFail = function(pr) {
passFailFlag);
	passFailFlag = pr;
};
/**
 * User middleware
 */

exports.userByID = function (req, res, next, id) {
	if (passFailFlag) {
		req.profile = config.anonymousUser;
		next();
	} else {
		return next(new Error('Failed to load User ' + id));
	}
};

/**
 * Require login routing middleware
 */
exports.requiresLogin = function (req, res, next) {
	if (passFailFlag) {
		next();
	} else {
		return res.status(401).send({
			message: 'User is not logged in'
		});
	}
};

exports.validLogin = function (req) {
	//console.log('***validLogin*** passFailFlag= ' + passFailFlag);
	return passFailFlag;
};

exports.isAuthorized = function (req, roles) {
	return passFailFlag;
};

/**
 * User authorizations routing middleware
 */
exports.hasAuthorization = function (roles) {
	return passFailFlag;
};

This auth mock will let you dynamically set whether an auth test should pass or fail within an individual test!
Note that it exports a function that lets you set the value of a pass/fail flag that it uses to determine whether it passes or fails authorization.

Now, to test an authorization failure:

describe('taskJobs.Server.Controller.Test - Auth Fail Show Task Jobs', function() {
   it('should fail to return a list of jobs', function(done) {
      var response = buildResponse();
      var request  = http_mocks.createRequest({
         method: 'GET',
         url: '/taskJobs'
      });
      response.on('end', function() {
         if (response.statusCode !== 302) {
            done(new Error('Incorrect Status Code: ' + response.statusCode));
         } else if (response._getRedirectUrl() !== '/') {
            done(new Error('Incorrect Redirect: ' + response._getRedirectUrl()));
         } else {
            done();
         }
      });
      users.passFail(false);
      controller.list(request, response);
      users.passFail(true);
   });
})

Note how we set the passFail flag
An auth failure results in a 302 (redirect) statusCode, AND the redirect url will be (in this case, anyway), = ‘/’. You can look in your controller and see what you do for each method when an authorization failure occurs. See my previous post on controller testing to see the controller that fits this example.

Without the auth mock, you can use the bulk of this code to test any redirect, just set the expected redirect url value, and the url in the request, and this code should just work.

Advertisements

About jeffmershon

Director of Program Management at SiriusXM.
This entry was posted in Software and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s