Closed davesag closed 10 years ago
You can just place your tests in different files (one file per controller) while putting global before
/ after
hooks only once in any of those files (or your can create testHelper.js
and put your global hooks there). All the tests from all the files passed to mocha
will run in between those two hooks.
Cool thanks. I'm not sure if this is 100% the correct way to approach it but it worked for me.
I created a file testHelper.js
as follows:
var Sails = require('sails');
global.assert = require('assert');
global.barrels = require('barrels');
global.sinon = require('sinon'), // Mocking/stubbing/spying
global.chai = require('chai'), // see http://chaijs.com/guide/styles/
global.expect = chai.expect, // Expectations lib
global.fixtures = null;
global.mockRequest = {};
global.mockResponse = {
ajaxRequired: sinon.spy(),
badRequest: sinon.spy(),
dbError: sinon.spy(),
forbidden: sinon.spy(),
notFound: sinon.spy(),
ok: sinon.spy(),
serverError: sinon.spy(),
unauthorised: sinon.spy(),
json: sinon.spy()
};
global.responseKeys = Object.keys(mockResponse);
// Global before hook
before(function (done) {
// Lift Sails with test database
console.log('Before all Location tests - lifting sails');
Sails.lift({
log: {
level: 'error'
},
connections: {
default: 'test'
}
}, function(err, sails) {
if (err) return done(err);
// Load fixtures
Location.destroy().exec(function(err, locs){
if (err) return done(err);
User.destroy().exec(function(err, users){
if (err) return done(err);
barrels.populate(function(err) {
fixtures = barrels.objects;
done(err, sails);
});
})
});
});
});
// Global after hook
after(function (done) {
console.log('After test - lowering sails');
sails.lower(done);
});
and then in my tests I do:
require("../testHelper");
var UserController = require('../../api/controllers/UserController');
// Here goes a module test
describe('User Controller', function() {
beforeEach(function(){
mockRequest = {
session: {},
body: {},
wantsJSON: true,
flash: {}
};
});
afterEach(function(){
for (var i = 0; i < responseKeys.length; i++ ) {
// console.log("resetting response." + responseKeys[i]);
mockResponse[responseKeys[i]].reset();
}
});
describe('validation', function() {
var goodBody = {
email: 'test-simple@test.tes'
},
badBody = {
email: 'nosuch-test@test.tes'
};
it('Can see the Users in the db', function(){
User.find(function(err, users){
var gotUsers = (fixtures.user.length > 0),
usersAreInTheDb = (users.length === fixtures.user.length);
assert(gotUsers, 'Expected fixture users');
assert(usersAreInTheDb, "Expected to find the users in the database");
});
});
it('returns true if requesting validation of the existence of an unknown email', function(done){
mockRequest.body = badBody;
UserController.validateEmailDoesNotExist(mockRequest, mockResponse);
setTimeout(function(){
expect(mockResponse.json.lastCall.args[0]).to.equal(true);
done();
}, 95);
});
// etc
});
});
And this works perfectly.
I read somewhere that I should not need to require("../testHelper") and that mocha
will load that for me, but I could not get that to work.
Also I have not been able to work out a way to pass a callback to, or return a Promise
from my controller methods, hence the use of setTimeout
. I am sure there's a better way however as this way is quite brittle.
Anyway - thanks for your help
Dave
Using your example I've got my app's controller tests working for one controller but now I want to break this out to test my other controllers.
How should I best do this so that I only list Sails once and load the fixtures once for the whole sequence of tests, with each test suite split out into a separate file?
Cheers
Dave