Подтвердить что ты не робот

Как издеваться над запросом и ответом в nodejs для тестирования промежуточного программного обеспечения/контроллеров?

Мое приложение имеет несколько уровней: промежуточное ПО, контроллеры, менеджеры. Интерфейс контроллеров идентичен среднему средству: (req, res, next).

Итак, мой вопрос: как я могу тестировать свои контроллеры без запуска сервера и отправки "реальных" запросов на localhost. То, что я хочу сделать, - создать запрос, экземпляры ответов как nodejs, а затем просто вызвать метод контроллеров.

Что-то вроде этого:

var req = new Request()
var res = new Response()
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)

Любые советы заслуживают высокой оценки. Спасибо!

P.S. причина, по которой я хочу сделать это, заключается в том, что в конце я хотел бы проверить, содержит ли объект ответа правильные переменные для представлений нефрита.

4b9b3361

Ответ 1

Там есть полупорядочная реализация в node-mocks-http

Требовать:

var mocks = require('node-mocks-http');

вы можете составить объекты req и response:

req = mocks.createRequest();
res = mocks.createResponse();

Вы можете проверить свой контроллер напрямую:

var demoController = require('demoController');
demoController.login(req, res);

assert.equal(res.json, {})

нюанс

В момент написания этой проблемы возникает проблема с тем, что излучатель события не запускается.

Ответ 2

Поскольку JavaScript является динамически типизированным языком, вы можете создавать макетные объекты и передавать их своим контроллерам следующим образом:

var req = {};
var res = {};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)

Если вашему контроллеру требуется конкретный фрагмент данных или функциональность из вашего объекта запроса или ответа, вам необходимо предоставить такие данные или функции в ваших маках. Например,

var req = {};
req.url = "http://google.com"; // fake the Url

var res = {};
res.write = function(chunk, encoding) { 
  // fake the write method 
};

var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)

Ответ 3

Я попытался бы использовать dupertest. Это модуль node, который я создал для самой простой проверки контроллера, не создавая нового сервера.

Он поддерживает привычный синтаксис модулей node, таких как request или supertest, но опять же, без необходимости разворачивать сервер.

Он работает так же, как и предложенный Гектором, но интегрируется с тестовой структурой, такой как Jasmine, чтобы чувствовать себя немного более бесшовной.

Пример, связанный с вашим вопросом, может выглядеть так:

request(controller.get_user)
  .params({id: user_id})
  .expect(user, done);

Или более явная версия с длинной версией:

request(controller.get_user)
  .params({id: user_id})
  .end(function(response) {
    expect(response).toEqual(user);
    done();
  });

Примечание: примеры предполагают, что user_id и user определены где-то, и что контроллер захватывает и возвращает пользователя на основе id.

Изменить: прочитав ответ на ответ выше, я признаю, что недостатком является то, что этот модуль по умолчанию не интегрирует более надежный mock-запрос или объект ответа. dupertest упрощает расширение и добавляет свойства как к req, так и к res, но по умолчанию они довольно голые.

Ответ 4

Если вы хотите использовать реальные объекты req и res, вам необходимо отправить реальные запросы на сервер. Однако это намного проще, чем вы думаете. Есть много примеров на экспресс github repo. Ниже показаны тесты для req.route

var express = require('../')
  , request = require('./support/http');

describe('req', function(){
  describe('.route', function(){
    it('should be the executed Route', function(done){
      var app = express();

      app.get('/user/:id/edit', function(req, res){

        // test your controllers with req,res here (like below)

        req.route.method.should.equal('get');
        req.route.path.should.equal('/user/:id/edit');
        res.end();
      });

      request(app)
      .get('/user/12/edit')
      .expect(200, done);
    })
  })
})

Ответ 5

Немного старый пост, но я бы хотел дать свои 2 цента. Подход, который вы хотите принять, зависит от того, выполняете ли вы модульное тестирование или интеграционное тестирование. Если вы идете вниз по пути использования supertest, это означает, что вы используете фактический код реализации, а это значит, что вы выполняете интеграционное тестирование. Если это то, что вы хотите сделать, это хорошо.

Но если вы выполняете модульное тестирование, вы будете макетировать объекты req и res (и любые другие связанные зависимости). В приведенном ниже коде (для краткости несовместимого кода) я высмеиваю res и даю только макетную реализацию json-метода, так как это единственный метод, который мне нужен для моих тестов.

// SUT
kids.index = function (req, res) {
if (!req.user || !req.user._id) {
    res.json({
        err: "Invalid request."
    });
} else {
    // non-relevent code
}
};

// Unit test
var req, res, err, sentData;
describe('index', function () {

    beforeEach(function () {
        res = {
            json: function (resp) {
                err = resp.err;
                sentData = resp.kids;
            }
        };
    });
    it("should return error if no user passed in request", function () {
        req = {};

        kidsController.index(req, res);
        expect(err).to.equal("Invalid request.");

    });

    /// More tests....
})

Ответ 6

Посмотрите на node-tdd и флаг useNock. Он построен поверх mocha и nock и автоматически создает и использует файл записи для каждого теста.

Мы любим, что это так просто в использовании. По сути, просто "включи и забудь" и сосредоточься на написании запросов/контрольных примеров. Если запросы на тестовые изменения, все равно необходимо удалить или настроить файл записи, но, по крайней мере, он полностью отделен от кода.