Обеспечение экспресс-приложения выполняется перед каждым тестом Mocha
Я работаю над разработкой REST API с помощью ExpressJS, NodeJS, Mongoose и Mocha.
Дело в том, что у меня есть файл app.coffee, который отвечает за настройку ExpressJS и подключение к Mongoose. Способ, которым я настроил это, заключается в том, что Mongoose подключен первым, и если это пройдет, то приложение ExpressJS будет запущено.
Проблема заключается в том, что при настройке Mocha мне нужно убедиться, что приложение ExpressJS, существующее в app.coffee, полностью запущено, включая весь асинхронный код, прежде чем какой-либо тестовый файл будет выполнен.
Для этого я создал test_helper.coffee и поместил в него следующий код, но тестовые окна начинают свое выполнение, даже если код в app.coffee не завершил свое выполнение полностью, что на самом деле имеет смысл:
before (done) ->
require(__dirname + '/../src/app')
done()
Вкратце, я хочу убедиться, что приложение ExpressJS полностью завершило настройку до того, как будет выполнен любой тестовый файл.
Как я могу это сделать?
Ответы
Ответ 1
Я опаздываю на вечеринку, но я нашел лучший способ настроить мой тестовый пакет для мокко для экспресс-приложения, чтобы сделать файл app.js или server.js экспортированным объектом приложения, например:
var mongoose = require('mongoose');
var express = require('express');
require('express-mongoose');
var env = process.env.NODE_ENV || 'development';
var config = require('./config/config')[env];
var models = require('./app/models');
var middleware = require('./app/middleware');
var routes = require('./app/routes');
var app = express();
app.set('port', process.env.PORT || config.port || 3000);
app.set('views', __dirname + '/app/views');
app.set('view engine', 'jade');
// database
mongoose.connect(config.db);
// middleware
middleware(app);
// Application routes
routes(app);
app.listen(app.get('port'));
console.log('Express server listening on port ' + app.get('port'));
// export app so we can test it
exports = module.exports = app;
убедитесь, что ваш файл конфигурации имеет разные среды, такие как разработка, тестирование, создание:
var path = require('path');
var rootPath = path.normalize(__dirname + '/..');
module.exports = {
development: {
db: 'mongodb://localhost/my_dev_db',
port: 3000
},
test: {
db: 'mongodb://localhost/my_test_db',
port: 8888
},
production: {
// ...
}
}
то в тестовых файлах вы можете пойти и потребовать от своего приложения, которое будет подключаться к правой панели и на правом порту:
var should = require('chai').should();
var request = require('supertest');
var mongoose = require('mongoose');
var app = require('../app');
var agent = request.agent(app);
var User = mongoose.model('User');
// get users
describe('GET /api/users', function() {
it('returns users as JSON', function(done) {
agent
.get('/api/users')
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if (err) return done(err);
res.body.should.have.property('users').and.be.instanceof(Array);
done();
});
});
});
И, наконец, чтобы запустить весь монстр, вы включите его в свой package.json
(убедитесь, что у вас есть nodemon и mocha в devDependencies):
"scripts": {
"start": "NODE_ENV=development ./node_modules/.bin/nodemon app.js",
"test": "NODE_ENV=test ./node_modules/.bin/mocha --reporter spec test/**.js"
}
Теперь вы можете запустить свой тестовый пакет с помощью npm test
и вашего приложения с помощью npm start
.
Надеюсь, это поможет!
ps: большая часть материала, который я изучил, рассматривая этот удивительный пример:
https://github.com/madhums/node-express-mongoose-demo
Ответ 2
Вам не нужно прослушивать порт для тестирования вашего приложения. Вы можете использовать supertest тестовую библиотеку с вашим приложением, и это должно быть нормально.
Вероятно, вам нужно будет подключиться к базе данных или клиенту redis. Вы можете сделать это в методе configure
вашего приложения. Поскольку node кэширует модули, вы можете потребовать модуль приложения в разных тестовых модулях без повторного подключения.
Ответ 3
Там может быть более простой способ, но я пошел в Grunt для автоматизации моих функциональных тестов. Там есть плагин express и mocha для достижения вашей цели. Мой файл grunt:
'use strict';
module.exports = function (grunt) {
grunt.initConfig({
express: {
options: {}
, test: {
options: {
script: './app.js'
}
}
}
, simplemocha: {
options: {
globals: ['should']
, timeout: 8000
, ignoreLeaks: false
, ui: 'bdd'
, reporter: 'tap'
}
, all: { src: ['tests/*.test.js'] }
}
})
grunt.loadNpmTasks('grunt-express-server')
grunt.loadNpmTasks('grunt-simple-mocha')
grunt.registerTask('default', ['express:test', 'simplemocha', 'express:test:stop'])
}
bonus: добавьте "grunt" как крюк git pre-commit. Таким образом, вы не можете совершать, не передавая все тесты
Ответ 4
Я столкнулся с той же проблемой при использовании jasmine/supertest для тестирования моего экспресс-приложения. Я решил проблему, выпуская, когда приложение было готово, и только после этого запускает мои тесты. Вот моя структура каталогов
- server.js
- spec
- setup.spec.js
- test.spec.js
В server.js
, когда ваш сервер настроен, и вы готовы запустить тесты, добавьте app.emit('started');
. И обязательно экспортируйте приложение! В setup.spec.js
вы можете наблюдать за выпуском события.
server.js
const express = require('express');
const app = express();
module.exports = app; // for testing
setTimeout(() => {
app.listen(process.env.PORT || 3000);
});
setup.spec.js
const server = require('../index');
beforeAll(done => server.on('started', done));
test.spec.js
const request = require('supertest');
const server = require('../index');
describe('test', () => {
it('test server works', done => {
request(server).get('/test').expect(200);
});
});
Такая же идея должна работать и на мокко. Вот статья, объясняющая это для мокко. Вы должны просто изменить beforeAll
на before
.
Ответ 5
Метод app.listen принимает обратный вызов, который запускается, когда все готово. Таким образом, вы должны иметь возможность пройти туда обратный вызов. Что-то вроде
before (done) ->
var app = require(__dirname + '/../src/app')
app.listen(3000, done)