首页 > 使用mocha+supertest 测试时在.end 中调用done() 的诡异异常

使用mocha+supertest 测试时在.end 中调用done() 的诡异异常

测试代码

var utils = require('./utils');
var request = require('supertest');
var should = require('should');
var app = require('../app');

describe('addition', function () {
  //... previous test
  it('should return 2 given the url /add/1/1', function (done) {
    request(app)
      .get('/add/1/1')
      .expect(200)
      .end(function (err, res) {
        should.not.exist(err);
        parseFloat(res.text).should.equal(2);
        done();
      });
  });
});

app.js 中需要测的路由

app.get('/add/:first/:second', function (req, res) {
  var sum = parseFloat(req.params.first) + parseFloat(req.params.second);
  res.send(200, String(sum));
});

上述测试会出现报错

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

但是我有在 .end 中调用done()

后来我把代码改为(去掉了done)

describe('addition', function () {
  //... previous test
  it('should return 2 given the url /add/1/1', function () {
    request(app)
      .get('/add/1/1')
      .expect(200)
      .end(function (err, res) {
        should.not.exist(err);
        parseFloat(res.text).should.equal(2);
      });
  });
});

反而没有报错,测试通过了.........

   ✓ should return 2 given the url /add/1/1

我不明白这其中的道理......

理论上讲,是需要有done 去提醒mocha 异步已经完成了。

mocha官网的描述与例子

Testing asynchronous code with Mocha could not be simpler! Simply invoke the callback when your test is complete. By adding a callback (usually named done) to it() Mocha will know that it should wait for completion.

describe('User', function() {
  describe('#save()', function() {
    it('should save without error', function(done) {
      var user = new User('Luna');
      user.save(function(err) {
        if (err) throw err;
        done();
      });
    });
  });
});

supertest上的例子

describe('GET /users', function() {
  it('respond with json', function(done) {
    request(app)
      .get('/users')
      .set('Accept', 'application/json')
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        done();
      });
  });
});

都需要调done, 但是我一调用done 就报错了,不调用done反而是好的。


不加 done 时,测试用例是同步的。这个时候异步回调里的断言不会执行,测试用例就过了。推测 app 里的代码有问题,请求超时了。


题主我也遇到了类似的问题

我是在koa2里用request模块,我把它包装成promise,然后mocha测试报的和题主一样的错。

function Prequest(params) {
    return new Promise(function (resolve, reject) {
        request(params, function (error, response, body) {
            if (error || !body || body.code != 1) {
                reject(error);
            }
            resolve(body);
        })
    });
}

不知道题主你是怎么解决的?


在end中的时候 ,最后执行的时候 测试的时候需要把对应的error传递进去,不传递导致error被promise拦截不往上走.

【热门文章】
【热门文章】