18

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

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

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

4

2 回答 2

29

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

您应该将应用程序的实际设置移动到一个单独的文件中,我们称之为 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();
  })
});
于 2012-07-17T23:07:12.390 回答
4

除了 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();
        });
    });

});
于 2014-07-01T15:22:36.447 回答