2017-12-25 6 views
0

Es gibt zwei Mokka-Testdateien:Node.js Mokka Sequelize Fehler ConnectionManager.getConnection wurde aufgerufen, nachdem der Verbindungsmanager geschlossen wurde

  1. einen Server erstellt und Pings es chai nur mit überprüfen, ob es
    Arbeits
  2. Erstellt einen Server und Tests Benutzer Einfügung in die Datenbank (sequelize postgres)

Beide Server eine Datenbankverbindung zu initialisieren.

Wenn lief unabhängig von ihnen beide passieren, wenn der zweite Ausfall lief zusammen mit dem folgenden Fehler:

Fehler ConnectionManager.getConnection wurde aufgerufen, nachdem der Verbindungsmanager

an der Konsole der Suche geschlossen wurde Die Verbindung mit der Datenbank wird für jeden Test zweimal eingerichtet, fungiert jedoch immer noch als ein einziger 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; 

Hauptservermodul:

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; 

Erster Testfall

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'); 
    }); 
}); 

Zweiter Testfall, 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: '[email protected]', 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: '[email protected]', 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); 
     }); 
    }); 
}); 

Antwort

0

Nachdem Sie weitere Untersuchungen dazu durchgeführt haben, ist dies das folgende Verhalten, das das Problem verursacht hat.

Wenn Mocha ausgeführt wird, um die Dateien rekursiv zu testen, wird es als ein einzelner Prozess ausgeführt, dies verursacht Konflikte beim Schließen der Verbindung mit Sequelize.

Um dieses Problem zu vermeiden Sie NICHT die Verbindung mit sequelize, schließen sollte aber setzen stattdessen eine zusätzliche Option mit Mokka --exit, die nach Tests abgeschlossen somit keine zusätzliche Zyklen in der Ereignisschleife endet, die sequelize Verbindung geschlossen von selbst.

Verwandte Themen