用摩卡测试Express和Mongoose

时间:2015-03-10 11:24:19

标签: node.js testing express mongoose mocha

我尝试使用Mocha和Chai测试我的REST API端点处理程序,该应用程序是使用Express和Mongoose构建的。我的处理程序大多是以下形式:

var handler = function (req, res, next) {
    // Process the request, prepare the variables

    // Call a Mongoose function
    Model.operation({'search': 'items'}, function(err, results) {
        // Process the results, send call next(err) if necessary

        // Return the object or objects
        return res.send(results)
    }
}

例如:

auth.getUser = function (req, res, next) {
    // Find the requested user
    User.findById(req.params.id, function (err, user) {
        // If there is an error, cascade down
        if (err) {
            return next(err);
        }
        // If the user was not found, return 404
        else if (!user) {
            return res.status(404).send('The user could not be found');
        }
        // If the user was found
        else {
            // Remove the password
            user = user.toObject();
            delete user.password;

            // If the user is not the authenticated user, remove the email
            if (!(req.isAuthenticated() && (req.user.username === user.username))) {
                delete user.email;
            }

            // Return the user
            return res.send(user);
        }
    });
};

这个问题是函数在调用Mongoose方法时会返回并测试这样的情况:

it('Should create a user', function () {
    auth.createUser(request, response);

    var data = JSON.parse(response._getData());
    data.username.should.equal('some_user');
});

在执行任何操作之前,函数返回时永远不会传递。使用Mockgoose模拟Mongoose,并使用Express-Mocks-HTTP模拟请求和响应对象。

虽然使用superagent和其他请求库是相当普遍的,但我更愿意单独测试函数,而不是测试整个框架。

有没有办法在评估should语句之前让测试等待而不更改代码我测试返回promises?

2 个答案:

答案 0 :(得分:1)

您应该使用测试的异步版本,方法是为done提供一个it参数的函数。

有关详细信息,请参阅http://mochajs.org/#asynchronous-code

由于您不想修改代码,因此一种方法是在测试中使用setTimeout等待调用完成。

我会尝试这样的事情:

it('Should create a user', function (done) {
    auth.createUser(request, response);

    setTimeout(function(){
        var data = JSON.parse(response._getData());
        data.username.should.equal('some_user');

        done(); 
     }, 1000); // waiting one second to perform the test
});

可能有更好的方式

答案 1 :(得分:0)

显然,express-mocks-http不久前被放弃了,新代码在node-mocks-http下。使用这个新库可以做我要求使用事件的事情。它没有记录,但查看代码,你可以弄明白。

创建响应对象时,必须传递EventEmitter对象:

var EventEmitter = require('events').EventEmitter;
var response = NodeMocks.createResponse({eventEmitter: EventEmitter});

然后,在测试中,您将为该事件添加一个监听器' end'或者'发送'因为它们都是在调用res.send时触发的。 '端'如果你有res.send以外的电话(例如,res.status(404).end()。

,则发送超过' send'

测试看起来像这样:

it('Should return the user after creation', function (done) {
    auth.createUser(request, response);

    response.on('send', function () {
        var data = response._getData();

        data.username.should.equal('someone');
        data.email.should.equal('asdf2@asdf.com');

        done();
    });
});