如何使用 Jasmine 2.3 和 SuperTest 测试 Express.js 路由

How to test Express.js routes with Jasmine 2.3 and SuperTest

我正在使用 Jasmine 2.3 通过 NPM 安装并使用 G运行t 执行。

'use strict';

module.exports = function(grunt) {
    grunt.initConfig({
        package: grunt.file.readJSON('package.json'),
        exec: {
            jasmine: 'node_modules/.bin/jasmine'
        }
    });
    require('load-grunt-tasks')(grunt);
    require('time-grunt')(grunt);
    grunt.registerTask('default', 'exec:jasmine');
};

我导出了一个 Express.js 应用程序对象,并在我的规范中将其与 SuperTest 一起使用。

'use strict';

var supertest = require('supertest')
var application = require('../../../../../server');

describe('GET /api/users', function() {
    it('should respond with json', function(done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, done);
    });
});

当我 运行 规范时,我没有得到任何错误,即使 200 状态代码是预期的,结果是 404。是 Jasmine 还是 SuperTest 的问题,或者我应该使用 SuperAgent.

我没有路由设置,只是在 Express 应用程序对象上设置了一个 404 错误处理程序。

application.use(function(request, response, next) {
    response
        .status(404)
        .send({
            message: 'not found'
        });
});

首先,问得好!我学到了一些研究这个的东西。显然 Jasmine + Supertest 不能一起玩得很好。原因似乎是 Supertest 调用 done(err),但 Jasmine 只会在调用 done.fail()fail() 时失败。您可以看到一些 github 个问题 here, and here

使用此代码查看证明:

describe('GET /api/users', function() {
    it('should respond with json', function(done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200, function(res){
              console.log(res); 
              //res is actually an error because supertest called done(error)!
              done.fail() //Now jasmine will actually fail
            });
    });
});

鉴于此,最简单的解决方案似乎是使用可以很好地协同工作的替代库。我个人使用摩卡咖啡代替茉莉花,并且取得了很好的成功。这是你的选择!

如果你真的想要,你可以使用 jasmine 并编写你自己的验证器,参见超级测试文档 here

希望对您有所帮助!

测试失败的原因是因为 Supertest 调用 done(err) 而 Jasmine 在 done.fail()fail() 上失败。尽管如此,还是有办法让 Jasmine 和 Supertest 一起工作。

看看这个:

describe('GET /api/users', function() {
  it('should respond with json', function(done) {

    supertest(application)
      .get('/api/users')
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(err, res) {

        if (err) {

          done.fail(err);

        } else {

          done();
        }
      });
  });
});

增加

.end(function(err, res) {

  if (err) {

    done.fail(err);

  } else {

     done();
  }
});

在描述块中的所有超级测试的 end 中应该解决超级测试和 Jasmine 之间的问题。这还将在控制台中提供一些贴心的错误描述。

为了避免在每个.end()函数中写逻辑。我建议在所有 jasmine 规范之前使用以下代码片段(或者如果您愿意,可以将其放入辅助文件 helpers/tell-jasmine.js):

function tellJasmine(done) {
    return function (err) {
        if (err) {
            done.fail(err);
        } else {
            done();
        }
    };
}


现在你可以在超级测试结束时写 .end(tellJasmine(done)):

describe('GET /api/users', function () {
    it('should respond with json', function (done) {
        supertest(application)
            .get('/api/users')
            .set('Accept', 'application/json')
            .expect('Content-Type', /json/)
            .expect(200)
            .end(tellJasmine(done));
    });
});

此代码归功于 nesQuick