我有一个MEAN应用程序,我试图让测试在节点方面工作。异步事件包含在promises中,它们在控制器中使用。我在测试控制器时失败了:(
控制器我试图测试:
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
是我们的数据来源,它会返回一个承诺(mpromise
,因为我们正在使用mongoose
,但它并不重要):
因此,在我们的测试中,我们尝试模拟请求(我们将依赖注入容器从中间件注入req
)和响应(如果调用了response.json()
,则测试成功我们试图获取的主题)和subjectRepository。我们使用bluebird
(虽然我是出于挫败感尝试了其他人)来为我们的模拟subjectRepository
创建假承诺:
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();
});
});
问题:如何在承诺成功后让测试运行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
}
答案 0 :(得分:1)
您的代码错误地将业务逻辑与前向路由混合在一起。
如果你的getAll 不触摸了请求和响应对象,它将看起来像这样:
ProjectController.prototype.getAll = function(subjectId) {
return req.dic.subjectRepository.getById(subjectId).then(function(subject){
return subject.projects;
});
};
现在,它不再与请求响应生命周期或逻辑负责相关,测试它是微不足道的:
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("...");
});
});