testing一个消费诺言的函数

我有一个平均的应用程序,我试图让testing工作在节点端。 asynchronous事件封装在控制器中使用的promise中。 我在testing控制器:(

我试图testing的控制器:

ProjectController.prototype.getAll = function(req, res, next) { req.dic.subjectRepository .getById(req.params.subjectId) .then(function(subject) { res.json(subject.projects); }, function(err) { return res.status(404).send('Subject does not exist.' + err); }); }; 

subjectRepository是我们的数据源,它返回一个promise( mpromise因为我们正在使用mongoose ,但不应该):

所以在我们的testing中,我们试着嘲笑请求(我们正在从一个中间件注入我们的dependency injection容器到req )和响应(如果response.json()已经被我们试图获取的主题调用,testing成功)和我们的subjectRepository。 我们使用bluebird (虽然我尝试了其他人的挫折)为我们的subjectRepository创build假承诺:

 describe('SubjectController', function() { 'use strict'; var Promise = require('bluebird'); it('gets all existing subjects', function() { // ------------------------------------- // subjectRepository Mock var subjectRepository = { getAll: function() {}, }; var subjectPromise = Promise.resolve([ {name: 'test'}, {name: 'test2'}, ]); spyOn(subjectRepository, 'getAll').andReturn(subjectPromise); // ------------------------------------- // request mock var req = { dic: { subjectRepository: subjectRepository, }, }; // ------------------------------------- // response mock var res = { json: function() {}, send: function() {}, }; spyOn(res, 'json'); // ------------------------------------- // actual test var subjectController = new (require('../../../private/controllers/SubjectController'))(); subjectController.getAll(req, res); // this succeeds expect(subjectRepository.getAll).toHaveBeenCalled(); // this fails // expect(res.json).toHaveBeenCalled(); }); }); 

问题:如何使testing运行expect()后承诺成功?

节点v0.12

代码在GitHub上,对于任何感兴趣的人来说: https : //github.com/mihaeu/fair-projects

也许我应该提到,从路由器调用控制器:

 // router handles only routing // and controller handles data between view and model (=MVC) subjectRouter.get('/:subjectId', subjectController.get); 

我通过改变我们的控制器来实现这个承诺,但是我不确定这是我们想要的。 没有办法让我的工作方法?

  it('gets all existing subjects', function(done) { // ... var subjectController = new (require('../../../private/controllers/SubjectController'))(); subjectController.getAll(req, res).then(function() { expect(res.json).toHaveBeenCalledWith(testSubjects); // success }).finally(done); expect(subjectRepository.getAll).toHaveBeenCalled(); // success } 

您的代码会导致将业务逻辑与前置路由混合的错误。

如果你的getAll没有触及到请求和响应对象,它看起来像这样:

 ProjectController.prototype.getAll = function(subjectId) { return req.dic.subjectRepository.getById(subjectId).then(function(subject){ return subject.projects; }); }; 

现在,它不再与请求响应生命周期或逻辑负责,testing它是微不足道的:

 it("does foo", function(){ // resolve to pass the test, reject otherwise, mocha or jasmine-as-promised return controller.getAll(152).then(...) }); 

这将使您的实际处理程序如下所示:

  app.get("/projects", function(req, res){ controller.getAll(req.params.subjectId).then(function(result){ res.json(result); }, function(){ res.status(404).send("..."); }); });