Как протестировать маршруты Express.js с помощью Jasmine 2.3 и SuperTest

Я использую Jasmine 2.3, установленный через NPM и запущенный с помощью Grunt.

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

У меня нет настройки маршрутов, только настройка обработчика ошибок 404 в объекте приложения Express.

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

person Zorin Greene    schedule 13.05.2015    source источник
comment
Я полагаю, что SuperTest использует SuperAgent внутри, так что это не должно быть проблемой. Как вы проверяете, что ответ является 404? Не могли бы вы показать нам код вашего маршрутизатора?   -  person Brennan    schedule 13.05.2015
comment
Роутер не настроен, только обработчик ошибки 404.   -  person Zorin Greene    schedule 13.05.2015


Ответы (3)


Во-первых, хороший вопрос! Я узнал некоторые вещи, исследуя это. Очевидно, Jasmine + Supertest не очень хорошо сочетаются друг с другом. Причина этого, по-видимому, в том, что Supertest вызывает done(err), но Jasmine не работает только при вызове done.fail() или fail(). Вы можете увидеть некоторые проблемы с github здесь и здесь.

Используйте этот код, чтобы увидеть доказательство:

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 и написать свои собственные валидаторы, представленные в документации супертеста здесь.

Надеюсь, это поможет!

person Brennan    schedule 13.05.2015

Причина сбоя теста заключается в том, что 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 всех супертестов в блоке описания должны решать проблемы между супертестом и Жасмин. Это также предоставит некоторые приятные описания ошибок в консоли.

person datatype_void    schedule 01.08.2015
comment
Похоже, это не решает проблему с ответвлением supertest + jasmine-node версии 2.0. Параметр 'err', предоставленный для обратного вызова, неверен (вроде пустого объекта). - person bFunc; 05.11.2015
comment
Это не работает для меня, используя supertest-as-promised и jasmine 2. - person reutsey; 20.01.2016
comment
Добавление обратного вызова .end(function(){}) с помощью устраняет проблему. Он также печатает хорошее описание ошибки, как упоминалось в @datatype_void. Failures: 1) Application Route GET / should return http status 200 Message: Failed: expected 201 "Created", got 200 "OK" Stack: Error: expected 201 "Created", got 200 "OK". Это также дает вам возможность использовать хорошую библиотеку утверждений, например Chai. - person Mr. Doomsbuster; 11.09.2017

Чтобы не писать логику в каждой .end() функции. Я предлагаю использовать следующий фрагмент перед всеми вашими спецификациями жасмина (или вы можете поместить его во вспомогательный файл 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.

person nashwaan    schedule 22.09.2016