There are 2 mocha test files:
- Creates a server and pings it using chai just to check if it's
working - Creates a server and tests user insertion into database (sequelize postgres)
Both of these servers initialize a database connection.
When ran independently both of them pass, when ran together the second one fails with the following error:
Error ConnectionManager.getConnection was called after the connection manager was closed
Looking at the console, connection with the database is established 2 times for each test, but still acts as a single pool.
# db/index.js
global.TABLE_USERS = 'users';
const Promise = require('bluebird');
const Sequelize = require('sequelize');
const config = require('./../config');
const User = require('./User');
/**
* @return {Promise}
*/
const connect = () => {
return new Promise((resolve, reject) => {
let sequelize = new Sequelize(config.postgres.database, config.postgres.user, config.postgres.password, {
host: config.postgres.host,
dialect: 'postgres',
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
define: {
underscored: false,
freezeTableName: false,
charset: 'utf8',
dialectOptions: {
collate: 'utf8_general_ci'
}
},
});
let user = User(sequelize);
sequelize
.authenticate()
.then(() => {
resolve({
User: user,
sequelize: sequelize
})
})
.catch(err => {
console.error('Couldn\'t authenticate');
reject(err)
})
});
};
module.exports.connect = connect;
Main server module:
const express = require('express');
const bodyParser = require('body-parser');
global.Promise = require('bluebird');
let routing = require('./routing');
const config = require('./config');
const middleware = require('./middleware');
let database = require('./db');
let Repositories = require('./repositories');
let Services = require('./services');
let Controllers = require('./controllers');
const Promise = require('bluebird');
/**
* @property {http.Server} this.app
*/
class Server {
constructor() {
this.app = express();
}
/**
* @param {Function} beforeHook
*
*/
init(beforeHook = null) {
return this._initDatabaseConnection()
.then(() => {
this._initContainer(beforeHook);
this._initRoutes();
return this._initServer()
});
}
/**
*
* @param {Function} beforeHook
* @private
*/
_initContainer(beforeHook) {
this.container = {};
// Modify for testing before starting
if (typeof beforeHook === 'function') beforeHook(this);
this.container = Repositories(this.database);
this.container = Services(this.container);
this.controllers = Controllers(this.container);
}
/**
*
* @private
*/
_initRoutes() {
this.app.use(bodyParser.json());
middleware.handleCors(this.app);
this.app.use(routing({...this.controllers, ...this.services}));
middleware.handleErrors(this.app);
}
/**
*
* @private
*
* @return {Promise}
*/
_initServer() {
return new Promise((resolve, reject) => {
this.server = this.app.listen(config.app.port, () => {
console.log(`Server started listening in ${config.app.env} on port ${config.app.port}`);
resolve(this)
});
});
}
/**
*
* @return {Promise}
* @private
*/
_initDatabaseConnection() {
return database.connect()
.then(connection => {
this.database = connection;
console.log('Connected to the database');
return Promise.resolve()
})
}
/**
* @return {Promise}
*/
close() {
this.server.close();
return this.database.sequelize.close();
}
}
module.exports = Server;
First test case
const assert = require('assert');
const chai = require('chai'),
expect = chai.expect,
chaiHttp = require('chai-http');
chai.use(chaiHttp);
const Server = require('../../src/Server');
describe('Server app test', () => {
let server;
before(async () => {
server = await (new Server()).init();
});
after(async () => {
await server.close();
});
it('should say respond it\'s name', async () => {
let pingServer = () => {
return new Promise((resolve, reject) => {
chai.request(server.server)
.get('/')
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(200);
resolve(res.body)
});
});
};
let res = await pingServer();
assert.equal(res.msg, 'API server');
});
});
Second test case, UserControllerTest
const assert = require('assert');
const chai = require('chai'),
expect = chai.expect,
chaiHttp = require('chai-http');
chai.use(chaiHttp);
const sinon = require('sinon');
const Promise = require('bluebird');
const Response = require('./../../src/lib/RequestHelper');
const UserValidation = require('./../../src/validation/UserValidation');
const Server = require('./../../src/Server');
const ReCaptchaService = require('./../../src/services/ReCaptchaService');
const ValidationError = require('./../../src/errors/ValidationError');
describe('/users/signup', () => {
describe('valid reCaptcha scenario', () => {
let server, reCaptchaServiceStub;
before(async () => {
reCaptchaServiceStub = sinon.stub(ReCaptchaService.prototype, 'authenticate').returns(true);
function setReCaptchaServiceStub(server) {
server.services = {ReCaptchaService: new reCaptchaServiceStub()};
}
server = await (new Server()).init(setReCaptchaServiceStub);
});
after(async () => {
reCaptchaServiceStub.restore();
await server.database.User.destroy({where: {}});
await server.close();
});
beforeEach(async () => {
await server.database.User.destroy({where: {}});
});
it('should allow user to register', async () => {
let data = {email: 'myemail@gmail.com', password: '1234'};
data[UserValidation.CAPTCHA_RESPONSE] = 'captcha_token';
let signUp = (data) => {
return new Promise((resolve, reject) => {
chai.request(server.server)
.post('/users/signup')
.send(data)
.end((err, res) => {
console.log(res.body)
expect(err).to.be.null;
expect(res).to.have.status(Response.STATUS_OK);
resolve(res.body)
});
});
};
let res = await signUp(data);
expect(res.token).to.be.a('string');
});
});
describe('invalid reCaptcha scenario', () => {
let server, reCaptchaServiceStub;
before(async () => {
reCaptchaServiceStub = sinon.stub(ReCaptchaService.prototype, 'authenticate')
.onCall()
.throws(new ValidationError('some err'));
function setReCaptchaServiceStub(server) {
server.container.ReCaptchaService = new reCaptchaServiceStub()
}
server = await (new Server()).init(setReCaptchaServiceStub);
});
after(async () => {
reCaptchaServiceStub.restore();
await server.close();
});
beforeEach(async () => {
await server.database.User.destroy({where: {}});
});
it('should send a bad request on invalid reCaptcha', async () => {
let data = {email: 'myemail@gmail.com', password: '1234'};
data[UserValidation.CAPTCHA_RESPONSE] = 'random_token';
let signUp = (data) => {
return new Promise((resolve, reject) => {
chai.request(server.server)
.post('/users/signup')
.send(data)
.end((err, res) => {
expect(err).to.not.be.null;
expect(res).to.have.status(Response.STATUS_BAD_REQUEST);
resolve(res.body);
});
});
};
let res = await signUp(data);
expect(res.err).to.equal(UserValidation.ERR_INVALID_RECAPTCHA);
});
});
});
Aucun commentaire:
Enregistrer un commentaire