我有一个运行快递的https服务器,我使用mocha和supertest进行测试。
我的问题是 - 如果我只运行测试 - 确定。如果我尝试运行带有测试的gruntfile然后运行express - 我看到很多EADDRINUSE错误,即使在测试文件中我用app.close()做后()。 同样适用于测试中的观察任务。
这是我的exapmle测试:
/* jshint node: true*/
/*global describe, it, after*/
(function() {
'use strict';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var request = require('supertest');
var app = require('../server.js').app;
var expect = require('chai').expect;
var Cookies;
after(function(done) {
app.close();
setTimeout(function(){done();}, 1500);
});
describe('/login', function() {
it('should auth the user', function(done) {
request(app)
.post('/login')
.send({login: "test", password: 'test'})
.expect(302)
.end(function(err, res) {
expect(err).to.be.equal(null);
expect(res.text).to.be.equal("Moved Temporarily. Redirecting to /");
Cookies = res.headers['set-cookie'].pop().split(';')[0];
done();
});
});
});
// testing API for serving session data for angualar factory
describe('/api/session', function() {
it('should return session data in JSON', function(done) {
var req = request(app).get('/api/session');
req.cookies = Cookies;
req.set('Accept','application/json')
.end(function(err, res) {
expect(err).to.be.equal(null);
expect(res.body).to.have.property("_id");
done();
});
});
});
}());
我知道那些测试远非完美。我正在通过适当的软件测试开始我的冒险。
所有这些"端口已经在使用"是显而易见的,没有一个......给出任何问题。所有测试工作正常,服务器工作正常,但stdout很疯狂。这种行为远非理想,可能充满了潜在的问题和不稳定性问题。
我的问题是 - 如何摆脱它?
我的想法是:
在不同的端口上创建专用服务器进行测试。不幸的是,我必须弄清楚如何实现这一点。
为superagent设置一些条件,如果它没有运行则运行服务器,或者只是......否则将其传递给superagent?
使用其他东西然后superagent(如请求,但我不确定是否所有cookie和node_tls_reject_unauthorized都能正常工作。
正如你所看到的 - 我对这个主题很挣扎,问题多于答案,而且没有足够的经验知道在哪里看。
我很感激任何帮助。
编辑:
我发现,我能做到:
before(function(done) {
app.listen(3001, function() { done(); });
});
开始在另一个端口上测试,但是...整个server.js仍然被加载,所以它也开始了。然后,当它与正在运行的服务器一起启动时,显然有EADDRINUSE。
答案 0 :(得分:6)
使用superagent
时,应始终将已配置的Express应用程序(中间件已注册,控制器路由等)传递给它 - 但未初始化为HTTP服务器。它会为您做到这一点,它会通过http.createServer
推迟到操作系统选择一个可用的端口。
如果您当前已经server.js
模块已经提供了一个完整的HTTP服务器的静态实例,那很可能是您的问题的根源。在任何一种情况下,尝试从实际的服务器实例化中提取应用程序配置/ bootstrapping,如下所示:
// server.js
var express = require('express');
var middleware = require('./middleware');
var controllers = require('./controllers');
// Configures the Express application instance.
exports.setup = function (app) {
app.use(middleware.foo);
app.get('/bar', controllers.bar);
app.locals.baz = 'quux';
}
// You might shoot yourself in the foot if parts of your application depend
// on a static reference at `server.app`.
exports.app = setup(express());
exports.app.listen(3000);
然后,在你的测试中,你可以做一些事情:
// tests.js
var express = require('express');
var server = require('./server');
describe('Server tests', function () {
// Create a fresh server instance prior to each test
beforeEach(function createNewSever() {
this.app = server.setup(express());
});
describe('Foo', function () {
it('barrs', function () {
request(this.app) // initializes a server instance on port A
// ... supertests
});
it('bazzes', function () {
request(this.app) // initializes a server instance on port B
// ... more supertests
});
});
});
这仅用于说明目的,其中实例化应用程序实例的时间/方式取决于您的测试上下文。要带走的重要一点是,您应该能够为您的测试用例创建新的,干净的,独立且隔离的服务器实例。如果您使用并行或以随机顺序执行测试的测试运行器,则绝对必要。