gpt4 book ai didi

node.js - 测试一个使用 promises 的函数

转载 作者:行者123 更新时间:2023-11-28 20:40:47 25 4
gpt4 key购买 nike

我有一个 MEAN 应用程序,我正在尝试让测试在 Node 端运行。异步事件包装在 promise 中,在 Controller 中使用。我没能测试 Controller :(

我要测试的 Controller :

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,但它应该没关系):

因此在我们的测试中,我们尝试模拟请求(我们将我们的依赖注入(inject)容器从中间件注入(inject)到 req 中)和响应(如果 response.json() 则测试成功 已使用我们尝试获取的主题和我们的 subjectRepository 调用。我们使用 bluebird(尽管出于挫败感我尝试了其他方法)为我们模拟的 subjectRepository 创建虚假 promise :

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();
});
});

问题:如何让测试在 promise 成功后运行 expect()

Node v0.12

所有感兴趣的人都可以在 GitHub 上找到该代码:https://github.com/mihaeu/fair-projects

也许我应该提到 Controller 是从路由器调用的:

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

我通过更改我们的 Controller 来传递 promise 来实现这一点,但我不确定这是否是我们想要的。有没有办法让我的方法发挥作用?

  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;
});
};

现在,它不再与请求响应生命周期相关或负责逻辑,通过以下方式测试它很简单:

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("...");
});
});

关于node.js - 测试一个使用 promises 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33763893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com