【问题标题】:Mocha timeout exceeded no matter what无论如何都超过了摩卡超时
【发布时间】:2015-04-30 16:59:45
【问题描述】:

我目前正在用 mocha 为我的 nodejs 应用程序编写测试。我的 api 调用要求我登录,所以我想创建一个包装测试套件,它创建一个测试用户,然后调用实际的测试套件。下面是代码的样子:

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;

这是一个使用包装器的测试套件:

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

无论我给测试套件什么超时,它都会给出“错误:超过 5000 毫秒的超时”。除了“它应该运行测试套件”之外,所有测试都通过了。我还要注意,我还有其他不使用包装器的测试文件。首先调用上面的这个测试套件,创建管理员用户,测试套件超时,然后清除管理文档,然后继续进行其他测试。最后,它打印出围绕 ConfigureAdmin 函数包装的测试。

【问题讨论】:

    标签: node.js asynchronous mongoose mocha.js supertest


    【解决方案1】:

    在你的包装器中,你有这个:

    // 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 函数包含更多对describeit 的调用。 如果您这样做,Mocha 不会引发任何错误,但它不会按您预期的方式工作。 Mocha 执行如下测试:

    1. Mocha 发现测试。 describe 调用 Mocha 注册新套房。他们的回调立即执行。 it 调用使用 Mocha 注册新测试。它们的回调在Mocha 运行测试时执行。钩子调用(beforeafter 等)也在向 Mocha 注册钩子,以便稍后执行,在 Mocha 运行测试时

    2. Mocha 运行已注册的测试。

    当你把describe 放在it 里面时,会出现一个问题:这个describe 被执行并且Mocha 注册一个新套件,但是到时候它已注册,执行流程您所有的describe 回调之外。因此,这个新套件在匿名顶级套件(Mocha 自动创建)上注册,并从该顶级套件继承其超时值。看看这个例子:

    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 ...]
    

    请注意 inner 套件,即使它出现在 JavaScript 代码中的 top 内部,但在 Mocha 的报告中显示在它的外部。 (另一方面,inner 2 恰好出现在它应该出现的位置。)这就是我上面解释的内容:当 Mocha 注册这个套件时,执行流程在 toptop 2 describe 之外来电。还要注意timeout 调用是如何无用的。

    如果您运行上述相同的代码但使用mocha --timeout 7000,则测试将通过,因为默认超时值(包括 Mocha 创建的匿名套件)现在是 7000。

    此外,您的套件目前需要在测试之间有一定的顺序。摩卡不是为此而设计的。为您的测试设置夹具应该在beforebeforeEach 钩子中完成,而拆除它们应该在afterafterEach 中完成。因此,这不仅仅是将describe 排除在it 调用之外的问题。

    【讨论】:

      猜你喜欢
      • 2016-08-24
      • 2019-06-13
      • 1970-01-01
      • 2014-11-22
      • 2014-03-23
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多