2015-02-06 59 views
2

最近我从使用回调切换到在我的rest api express应用程序中使用promise。 但我在单元测试路由/控制器与承诺的异步行为有麻烦。以下是需要进行单元测试的示例代码。Node.js中的单元测试承诺代码表示路由/控制器

var handler = function (req, res, next) { 
    var query = {}, 
    var options = { 
    sort: { updatedAt: -1 }, 
    limit: 10 
    }; 
    if (req.query.before) { 
    query.updatedAt = { $lt: req.query.before }; 
    } 
    // User.findAsync returns bluebird promise 
    User.findAsync(query, null, options).then(function (user) { 
    res.json(user); 
    }).catch(function (e) { 
    next(e); 
    }); 
} 
router.get('/api/users', handler); 

我的测试上面的代码的做法是窥探REQ,下一步,User.findAsync和检查,如果他们被称为使用正确的参数。但由于承诺的异步行为,我无法检查res.json或next是否被调用。

我试着存根findAsync返回已解决的承诺(Promise.resolve(user))。但仍然是回调异步执行。

我不确定我是否正在测试快速应用程序的正确轨道。

测试这种代码的良好分离策略是什么?

我也听说过使用supertest。 但是对于我来说,使用supertest从http端点测试看起来更像是集成测试,它不是单元测试,而且非常昂贵。另外,一般来说,我想知道尝试使用单元测试(模型,控制器,中间件等)覆盖所有代码是否是好的做法,以及有什么好的策略或技术来做到这一点。或者,如果它足以用超级测试测试http端点。

+0

你使用什么测试框架?摩卡拥有良好的异步测试支持(我认为它可以用于承诺没有太多的困难)。也许你可以发布你的测试用例? – 2015-02-06 20:58:00

+0

我使用摩卡作为测试框架与sinon。我没有遇到单元测试返回承诺的函数,但我的路由/控制器函数没有返回promise,它只是调用res.json或next然后回调。这是我有困难的地步。 – jryu 2015-02-06 22:08:46

回答

3

如果您的测试方法未返回承诺,那么您无法在Mocha中使用promise语法。您可以像测试任何其他异步方法一样测试您的方法 - 以done作为参数it。比方说,我们想测试你的handler功能:

var handler = function (req, res, next) { 
    //... 
    User.findAsync(query, null, options).then(function (user) { 
    res.json(user); 
    }).catch(function (e) { 
    next(e); 
    }); 
} 

我们可以写一个测试为这样:

describe("The handler", function(){ 
    it("calls res.json", function(done){ // note the done argument 
     handler({query: {before: 5}, // mock request 
       {json: done} // res.json calls our `done` param of this function 
       function(){ throw new Error("error called"); }); 
    }); 
}); 

请注意,我们嘲笑请求,响应和next处理。我们的模拟响应有一个json方法,它可以让测试知道它是完整的(这可以是一个函数,如果你想在它内部作出断言),并且如果调用next,我们会抛出信号来表明它不是应该发生的事情。