Как мне проверить моё экспресс приложение с мокко? - PullRequest
65 голосов
/ 12 января 2012

Я только что добавил в свое экспресс-приложение mustjs и mocha, но мне интересно, как протестировать мое приложение. Я хотел бы сделать это так:

app = require '../app'
routes = require '../src/routes'

describe 'routes', ->
  describe '#show_create_user_screen', ->
    it 'should be a function', ->
      routes.show_create_user_screen.should.be.a.function
    it 'should return something cool', ->
      routes.show_create_user_screen().should.be.an.object

Конечно, последний тест в этом тестовом наборе просто сообщает med, что функция res.render (вызываемая в show_create_user_screen) не определена, возможно, потому что сервер не запущен, а конфигурация не выполнена. Поэтому мне интересно, как другие люди настраивают свои тесты?

Ответы [ 5 ]

64 голосов
/ 09 июля 2012

нашел альтернативу в комплектах тестов connect.js

Они используют supertest для тестирования приложения подключения без привязки сервера к какому-либо порту и без использования mock-ups.

Вот выдержка из набора статических промежуточных программных соединений connect (с использованием mocha в качестве тестового прогона и супертестом для утверждений)

var connect = require('connect');

var app = connect();
app.use(connect.static(staticDirPath));

describe('connect.static()', function(){
  it('should serve static files', function(done){
    app.request()
    .get('/todo.txt')
    .expect('contents', done);
  })
});

Это работает и для приложений-экспрессов

32 голосов
/ 13 января 2012

ОК, во-первых, хотя тестирование кода маршрутизации - это то, что вы можете или не хотите делать, в общем, попытайтесь отделить интересующую вас бизнес-логику в чистом коде JavaScript (классах или функциях), который отделен от экспресс-или любой другой структуры, которую вы используете.использовать и использовать ванильный тест мокко, чтобы проверить это.Как только вы добились этого, если вы действительно хотите протестировать маршруты, которые вы настраиваете в mocha, вам нужно передать параметры mock req, res в функции промежуточного программного обеспечения, чтобы имитировать интерфейс между express / connect и вашим промежуточным программным обеспечением.

В простом случае вы могли бы создать фиктивный res объект с функцией render, который выглядит примерно так:

describe 'routes', ->
  describe '#show_create_user_screen', ->
    it 'should be a function', ->
      routes.show_create_user_screen.should.be.a.function
    it 'should return something cool', ->
      mockReq = null
      mockRes =
        render: (viewName) ->
          viewName.should.exist
          viewName.should.match /createuser/

      routes.show_create_user_screen(mockReq, mockRes).should.be.an.object

Также только функции промежуточного программного обеспечения FYI не должны возвращать какое-либо конкретное значение,это то, что они делают с параметрами req, res, next, на которых вы должны сосредоточиться при тестировании.

Вот некоторый JavaScript, как вы просили в комментариях.

describe('routes', function() {
    describe('#show_create_user_screen', function() {
      it('should be a function', function() {
        routes.show_create_user_screen.should.be.a["function"];
      });
      it('should return something cool', function() {
        var mockReq = null;
        var mockRes = {
          render: function(viewName) {
            viewName.should.exist;
            viewName.should.match(/createuser/);
          }
        };
        routes.show_create_user_screen(mockReq, mockRes);
      });
    });
  });
21 голосов
/ 19 июля 2012

Вы можете попробовать SuperTest, и тогда позаботятся о запуске и завершении работы сервера:

var request = require('supertest')
  , app     = require('./anExpressServer').app
  , assert  = require("assert");

describe('POST /', function(){
  it('should fail bad img_uri', function(done){
    request(app)
        .post('/')
        .send({
            'img_uri' : 'foobar'
        })
        .expect(500)
        .end(function(err, res){
            done();
        })
  })
});
6 голосов
/ 12 января 2012

Мокко поставляется с до, до каждого, после и после каждого для тестирования bdd.В этом случае вы должны использовать ранее в вашем описании вызова.

describe 'routes' ->
  before (done) ->
    app.listen(3000)
    app.on('connection', done)
5 голосов
/ 17 января 2012

Я обнаружил, что проще всего настроить класс TestServer, который будет использоваться как помощник, а также как вспомогательный http-клиент, и просто отправлять реальные запросы на настоящий http-сервер.Однако могут быть случаи, когда вы хотите вместо этого посмеяться над этим материалом.

// Test file
var http = require('the/below/code');

describe('my_controller', function() {
    var server;

    before(function() {
        var router = require('path/to/some/router');
        server = http.server.create(router);
        server.start();
    });

    after(function() {
        server.stop();
    });

    describe("GET /foo", function() {
        it('returns something', function(done) {
            http.client.get('/foo', function(err, res) {
                // assertions
                done();
            });
        });
    });
});


// Test helper file
var express    = require('express');
var http       = require('http');

// These could be args passed into TestServer, or settings from somewhere.
var TEST_HOST  = 'localhost';
var TEST_PORT  = 9876;

function TestServer(args) {
    var self = this;
    var express = require('express');
    self.router = args.router;
    self.server = express.createServer();
    self.server.use(express.bodyParser());
    self.server.use(self.router);
}

TestServer.prototype.start = function() {
    var self = this;
    if (self.server) {
        self.server.listen(TEST_PORT, TEST_HOST);
    } else {
        throw new Error('Server not found');
    }
};

TestServer.prototype.stop = function() {
    var self = this;
    self.server.close();
};

// you would likely want this in another file, and include similar 
// functions for post, put, delete, etc.
function http_get(host, port, url, cb) {
    var options = {
        host: host,
        port: port,
        path: url,
        method: 'GET'
    };
    var ret = false;
    var req = http.request(options, function(res) {
        var buffer = '';
        res.on('data', function(data) {
            buffer += data;
        });
        res.on('end',function(){
            cb(null,buffer);
        });
    });
    req.end();
    req.on('error', function(e) {
        if (!ret) {
            cb(e, null);
        }
    });
}

var client = {
    get: function(url, cb) {
        http_get(TEST_HOST, TEST_PORT, url, cb);
    }
};

var http = {
    server: {
        create: function(router) {
            return new TestServer({router: router});
        }
    },

    client: client
};
module.exports = http;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...