摩卡超时无论如何都超过了

我目前正在摩卡书写我的nodejs应用程序的testing。 我的API调用要求我login,所以我想创build一个包装testing套件,创build一个testing用户,然后调用实际的testing套件。 下面是代码的样子:

var request = require('supertest'); var config = require('../config/config'); var AdminUser = require('../models/Authmodel'); function configureAuth(test_suite) { var url = "localhost:" + config.port; var email = "test@test.com"; var password = "test_password"; var admin; var token; describe("Signup User", function() { it("should signup new user", function(done) { request(url) .post('/auth/signup') .send({ email: email, password: password }) .expect(200) .end(function(){ done(); }); }); it("should login the user", function(done) { request(url) .post('/auth/login') .send({ email: email, password: password }) .expect(200) .end(function(err,res){ if(err) throw(err); res.body.should.have.property('token'); token = res.body.token; done(); }); }); it("should retrieve admin document", function(done) { AdminUser.findOne({email: email}, function(err, dbAdmin) { if(err) throw(err); admin = dbAdmin; done(); }); }); }); // Call the actual test suite, pass it the auth credentials. describe("Test Suite", function() { it("should run the test suite", function(done) { // No matter what the timeout is set to it still exceeds it this.timeout(5000); test_suite({ email: email, password: password, token: token, admin: admin }, done); }); }); describe("Clear Admins", function() { it("should clear the admin table", function(done) { AdminUser.remove({email: email}, function(err) { if(err) throw(err); done(); }); }); }); }; module.exports = configureAuth; 

这里是一个使用包装器的testing套件:

 var request = require('supertest'); var config = require('../config/config'); // Wrapper that creates admin user to allow api calls var ConfigureAuth = require('./ConfigureAuth'); // Test data var templateForm = {...} var submittedForm = {...} ConfigureAuth( function(credentials, exit) { var url = "localhost:" + config.port; var templateFormId = null; describe("Form Templates", function() { describe('POST /api/form/template', function(){ it('should save the template', function(done){ request(url) .post('/api/form/template') .query({email: credentials.email, token: credentials.token}) .send({ _admin_id: credentials.admin._id, template: templateForm, }) .end(function(err, res){ templateFormId = res.body._id; res.body.should.have.property('_admin_id').and.be.equal(''+credentials.admin._id); res.body.should.have.property('template').and.be.instanceof(Object); done(); }); }); }); describe('GET /api/form/template/:id', function(){ it('Should respond with template data', function(done){ request(url) .get('/api/form/template/' + templateFormId) .query({email: credentials.email, token: credentials.token}) .end(function(err, res){ ... done(); }); }); }); describe('GET /api/form/template/company/:id', function(){ it('Should respond with company template data', function(done){ request(url) .get('/api/form/template/company/' + credentials.admin._id) .query({email: credentials.email, token: credentials.token}) .end(function(err, res){ ... done(); }); }); }); describe('DELETE /api/form/template/:template_id', function(){ it('Should delete the template data', function(done){ request(url) .delete('/api/form/template/' + templateFormId) .query({email: credentials.email, token: credentials.token}) .end(function(err, res){ ... done(); }); }); }); }); describe("Submitted Forms", function() { describe('POST /api/form/patient', function(){ it('should save submitted form', function(done){ request(url) .post('/api/form/patient') .query({email: credentials.email, token: credentials.token}) .send({ _admin_id: credentials.admin._id, form: submittedForm, firstName: "Jimbo", lastName: "Cruise", patientEmail: "jcruise@tomcruise.com", }) .end(function(err, res){ ... submittedFormId = res.body._id; done(); }); }); }); describe('GET /api/form/:form_id', function(){ it('should respond with submitted form data', function(done){ request(url) .get('/api/form/patient/' + submittedFormId) .query({email: credentials.email, token: credentials.token}) .end(function(err, res){ res.body.should.have.property('_id'); ... done(); }); }); }); }); after(function() { exit(); }); }); 

无论testing套件超时,它都会给出“错误:超过5000ms的超时”。 除“应该运行testing套件”外,所有testing都通过。 我也会注意到,我有其他的testing文件,不使用包装。 这个testing套件首先被调用,pipe理员用户被创build,testing套件超时,然后清除pipe理文件,然后进行其他testing。 最后,它打印出围绕ConfigureAdmin函数的testing。

在你的包装内,你有这样的:

 // Call the actual test suite, pass it the auth credentials. describe("Test Suite", function() { it("should run the test suite", function(done) { // No matter what the timeout is set to it still exceeds it this.timeout(5000); test_suite({ email: email, password: password, token: token, admin: admin }, done); }); }); 

test_suite函数包含更多的调用来describe it摩卡不会提出任何错误,如果你这样做,但它不会像你所期望的那样工作。 摩卡执行这样的testing:

  1. 摩卡发现了testing。 describe电话注册与摩卡新套房。 他们的callback是马上执行的。 it呼吁与摩卡注册新的testing。 当Mocha运行testing时,他们的callback被执行。 挂钩调用( beforeafter等)也正在向Mocha注册挂钩,稍后将在Mocha运行testing时执行挂钩。

  2. 摩卡运行已经注册的testing。

当你在里面describeit出现一个问题:这个describe 被执行,而且Mocha 将会注册一个新的套件,但是当它被注册的时候,执行的stream程就不在你describe所有callback之内了。 所以这个新的套件被注册在一个匿名的顶层套件(Mocha自动创build的套件)上,并从该顶层套件inheritance它的超时值 。 看看这个例子:

 describe("top", function () { it("test", function () { this.timeout(5000); describe("inner", function () { it("inner test", function (done) { setTimeout(function () { done(); }, 6000); }); }); }); describe("inner 2", function () { it("inner test 2", function () {}); }); }); describe("top 2", function (){ it("test 3", function () {}); }); 

如果你运行它,你会得到:

  top ✓ test inner 2 ✓ inner test 2 top 2 ✓ test 3 inner 1) inner test 3 passing (2s) 1 failing 1) inner inner test: Error: timeout of 2000ms exceeded [... etc ...] 

请注意,Mocha的报告显示, inner套件尽pipe出现在JavaScript代码的top ,但在其外部显示。 (另一方面, inner 2 ,恰好出现在它应该在的地方)。这就是我上面解释的内容:当Mocha注册这个套件时,执行stream程在toptop 2 describe调用之外。 请注意timeout通话是如何失效的。

如果你运行上面的代码,但使用mocha --timeout 7000 ,testing将会通过,因为默认的超时值,包括摩卡创build的匿名套件现在是7000。

另外,您的套件当前需要testing之间的特定顺序。 摩卡不是为此而devise的。 为您的testing设置固定装置应该在beforeEach钩子beforebefore完成,并且before beforeEach钩子之后应该完成afterEach 。 所以,这不仅仅是一个从it呼吁中被describe出来的it