【问题标题】:Setup/teardown of express.js application with mocha使用 mocha 设置/拆卸 express.js 应用程序
【发布时间】:2012-06-13 12:35:26
【问题描述】:

我正在尝试使用 mocha 创建一个独立的测试套件,在一个完美的世界中,它会启动我的 express.js 应用程序,使用僵尸来呈现页面,检查一堆东西,然后拆除/杀死 express。 .js 应用程序。

有没有简单/最好的方法来做到这一点?

注意。我可以在运行测试之前运行 express 应用程序服务器,但是如果你不打算刮牦牛有什么用呢。

【问题讨论】:

  • 好问题。我自己研究了一段时间,但一周后我就放弃了。我发现僵尸真的很烦人。我读了很多关于 PhantomJS 的文章,但我自己没有尝试过。

标签: node.js makefile express zombie.js


【解决方案1】:

首先,您需要将您的实际应用设置移动到一个模块中,然后将其导入到实际启动您的应用的文件中。现在这是分开的,您可以在实际收听之前让应用处于完整状态。

你应该将你的应用程序的实际设置移动到一个单独的文件中,我们称之为 app.js,可以从你运行节点的文件中调用监听,我们称之为 index.js。

所以,app.js 看起来像:

    var express = require('express')
  , routes = require('./routes');

var app = module.exports = express.createServer();

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// Routes

app.get('/', routes.index);

index.js 看起来像:

var app = require('./app');

app.listen(3000, function(){
  console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});

这将加载您的应用程序与实际监听它分开,允许您将该应用程序加载到您的单元测试中。

在你的单元测试中,你会在 setup 方法和 teardown 方法中做一些事情来启动和关闭服务器。

在文件 test/app_tests.js 中:

describe('app', function(){
  var app = require('../app');
  beforeEach(function(){
    app.listen(3000);
  });
  // tests here
  afterEach(function(){
    app.close();
  })
});

【讨论】:

  • 太棒了!但是,就我而言,我有多个测试文件,而且似乎 mocha 会同时执行所有文件,这会导致测试文件之间出现一些严重的冲突!我该怎么办?
  • 让每个测试在不同的端口上监听 - 只需选择一个随机数(足够高)
  • 出色的解决方案!这是正确的做法。一项修改:您实际上应该关闭 app.listen 的结果,而不是 app 本身,即:(在 beforeEach 中)“instance = app.listen(3000);” ...然后(在 afterEach 中)“instance.close()”
  • 你也可以这样做 if (!module.parent) { server.listen(8080); } 以防止服务器在测试中启动(并在每次测试之前和之后手动执行此操作)
【解决方案2】:

除了 Oved D 答案。

在 express-app.js 或其他文件中描述您的应用:

module.exports = function (o) {
  o = o || {};
  var app = express();

  // app.configure
  // configure routes
  if (o.someOption) {
    // some additional test code
  }

  return app;
}

在 test/01-some.js 中描述测试:

var expressApp = require('../express-app');
describe('some', function () {

  // just describe needed vars
  var app, server, port;

  // describe setup
  before(function (next) {
    // create app when 
    app = expressApp({routes: /api\/some\/.*/ /* put here some test options ...*/});
    // creating listener with random port
    server = app.listen(function () {
      // store port when it ready
      port = server.address().port;
      // and go to tests
      next();
    });
  });

  // tests
  it('should return valid result', function (done) {
    // do a simple request to /api/some
    http.request({
      host: 'localhost',
      port: port,
      path: '/api/some'
    }, function (res) {
      if (res.err) throw new Error(res.err);
      done();
    });
  });

  // teardown
  after(function () {
    // stop listening that port
    server.close();
  });

});

完成。 ;-)

现在您可以创建任意数量的类似测试。建议您通过将参数传递给 express-app.js 模块来定义测试中仅需要的 url 和服务。


更新:

不确定它在 mocha 中是如何工作的,但最好将 beforeafter 调用移动到 init.js 并使用 mocha --require init.js 加载它。

文件应该是这样的:

// use it in your mocha tests
global.setupEnv = function setupEnv (o, before, after) {

    // just describe needed vars
    var env = Object.create(null);

    // setup
    before(function (next) {
        // create app
        env.app = expressApp(o);
        // creating listener with random port
        env.server = env.app.listen(function () {
            // store port when it ready
            port = env.server.address().port;
            env.app.log('Listening on ', env.port);
            // and go to tests
            next();
        });
    });

    // teardown
    after(function () {
        // stop listening that port
        env.server.close();
    });

    return env;
}

在你的测试中:

// requiring dependencies
var request = require('request');

describe('api', function () {

    // describe setup
    var env = global.setupEnv({
            routes: 'api/some'
        }, before, after);

    // tests
    it('should pass', function (done) {
        request('http://localhost:' + env.port, function (error, response, body) {
            done();
        });
    });

});

【讨论】:

    猜你喜欢
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2018-09-06
    • 2015-03-17
    • 2016-12-23
    相关资源
    最近更新 更多