如何在node.js + Express.js + mongodb app上异步启动mocha测试

时间:2014-11-20 10:03:45

标签: node.js unit-testing asynchronous tdd mocha

问题似乎非常微不足道,所以我真的很尴尬,我无法自己解决它,但我在谷歌和stackoverflow上做了很多搜索,但没有任何帮助我。我正在使用node.js开发RESTful服务器,我想测试它的API。服务器异步初始化(它需要连接到db,从另一个服务器请求令牌等)。所以我的server.js文件中的代码如下所示:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient;
var bunyan = require('bunyan'); // logger
var routes = require('./routes/folrouter.js');
var TokenGetter = require('./utils/tokengetter');


MongoClient.connect('mongodb://localhost:27017/fol', function (err, db)
{
    if (err)
        throw err;

    global.db = db;
    global.log = bunyan.createLogger({
            name : "folserver",
            src : true,
            serializers: bunyan.stdSerializers,
            streams : [ {
                path : 'folserver.log',
                type : 'file'
            } ]
        });


    global.log.info("folserver starts...");
    var tg = new TokenGetter();
    tg.on("token_received", function(token){
        global.access_token = token;
        global.log.info("access_token received: " + token);
        //TO DO: compression and cache static content
        app.use(express.static(__dirname + '/public'));
        app.use(bodyParser.urlencoded({ extended: true } ));
        app.use(bodyParser.json());
        app.use('/api', routes);
        app.listen(8080);
        console.log('Express server listening on port 8080');
    });
    tg.getToken();

});

//only for tests!!!
module.exports = app;

我在package.json文件中定义了脚本操作,因此我可以使用“npm test”命令从命令行运行测试:

{
  "name": "folserver",
  "version": "0.0.0",
  "description": "Server side for my app",
  "main": "server.js",
  "dependencies": {
   ...
  },
  "devDependencies": {
    "mocha": "^2.0.1",
    "should": "^4.3.0",
    "supertest": "^0.15.0"
  },
  "scripts": {
    "test": "./node_modules/.bin/mocha   --require should  --reporter spec  --ui bdd  tests/tests.js",
    "start": "server.js"
  },
  "repository": "",
  "author": "PainKiller",
  "private": true
}

然后我的tests.js包含以下代码:

var should = require('should');
var request = require('supertest');
var app  = require('../server.js');
describe("user.js", function () {
    describe("#upsert()", function () {
        it("should insert new user object correctly", function () {
            before(function (done) {
                console.log("before");
                request(app)
                .post('api/user/upsert', user)
                .set('Accept', 'application/json')
                .end(function (error, res) {
                    done();
                });

            });

            after(function (done) {
                //after
                console.log("after");
                done();
            });

        });

        it("should update new user object correctly", function () {
            //Test Goes Here
        });
    });

    describe("#isregistered()", function () {
        it("should return false on id not in db", function () {
            //Test Goes Here
        });

        it("should return true on id in db", function () {
            //Test Goes Here
        });
    });
});

第一个问题 - 我的应用程序在测试开始后完全初始化 - 我在启动“npm test”时从我的应用程序中看到console.log输出。我看到我的测试在控制台中传递(它们在那时没有做任何事情,除了第一次,但它也通过了)第二 - 我从来没有在我的控制台中看到我的测试中的console.log输出 - 这真的让我很烦,可能这个代码永远不会运行?但如果这是真的,我怎样才能在控制台中看到我的测试结果?

我看到两种解决方法。首先 - 在开始测试之前做出延迟,我已经尝试过使用mocha的--outout命令 - 它没有帮助。到目前为止,我找不到一种适当而好的方法来停止执行一段时间的JS代码。第二 - 使用app发出事件,并开始对该事件进行测试,但我也是以这种方式失败了。也许我错了其他的东西,我只是没有看到它,所以我感谢任何帮助和评论。提前致谢!

2 个答案:

答案 0 :(得分:1)

使用回调参数调用测试函数。 Mocha will then run this function asynchronously

编辑: 只需重新组织你的钩子。

describe("#upsert()", function () {

    var result;

    before(function (done) {
         console.log("before");
         request(app)
         .post('api/user/upsert', user)
         .set('Accept', 'application/json')
         .end(function (error, res) {

             result = res;
             done();
        });

    });

        after(function (done) {
            //after
            console.log("after");
            done();
        });

    it("should insert new user object correctly", function () {

        // assert "result" object here
    });

    it("should update new user object correctly", function () {
        //Test Goes Here
    });
});

因为你在非异步函数中有“before()”。 it()将退出而不是等待before()完成。在外部放置异步准备函数或将其称为异步函数本身。

答案 1 :(得分:0)

所以我最终在测试前初始化我的应用程序时遇到了问题。这是最终代码:

var should = require('should');
var request = require('supertest');
var app = require('../server.js');

//this is root level hook  with setTimeout do the trick
before(function (done) { console.log("before all"); this.timeout(9000); setTimeout(done, 5000); });

describe("user.js", function () {
    describe("#upsert()", function () {
    before(function (done) {
                console.log("before 2");
                this.timeout(5000);
                var user = { test: "test" }
                request(app)
                .post('/api/user/upsert')
                .set('Content-Length', JSON.stringify(user).length)
                .set('Accept', 'application/json')
                .send(user)
                .end(function (error, res) {
                    if (error) throw error;
                    console.log(res);
                    done();
                });
                //done();
            });

        it("should insert new user object correctly", function (done) {
            console.log("it");
            //console.log(app);
            //console.log(global.db);
            done();

        });
        after(function (done) {
            console.log("after");
            done();
        });

        it("should update new user object correctly", function (done) {
            //Test Goes Here
            done();
        });
    });

    describe("#isregistered()", function (done) {
        it("should return false on id not in db", function (done) {
            //Test Goes Here
            done();
        });

        it("should return true on id in db", function (done) {
            //Test Goes Here
            done();
        });
    });
});

一切都是异常的,我在正确的位置看到所有的console.logs。