我的应用程序有几个层次:中间件,控制器,经理。 控制器接口是相同的中间件的一个:(REQ,RES,下一个)。
所以我的问题是:如何能测试我的控制器,而无需启动服务器并发送“真实”的请求到本地主机。 我想要做的是创建请求,响应实例作为它的NodeJS,然后只需调用控制器方法。
事情是这样的:
var req = new Request()
var res = new Response()
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
任何意见表示高度赞赏。 谢谢!
PS为什么我想这样做的原因是,在最后我想测试响应对象是否包含了玉的观点正确的变量。
Answer 1:
有在半体面实现节点嘲笑-HTTP
需要它:
var mocks = require('node-mocks-http');
那么你可以撰写REQ和响应对象:
req = mocks.createRequest();
res = mocks.createResponse();
然后,您可以直接测试你的控制器:
var demoController = require('demoController');
demoController.login(req, res);
assert.equal(res.json, {})
警告
有一个在这个实施写作问题与事件做发射不被解雇的时间。
Answer 2:
由于JavaScript是一种动态类型语言,您可以创建模拟对象,并将它们传递给你的控制器如下:
var req = {};
var res = {};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
如果你的控制器需要从您的请求或响应数据或功能的特定对象一块你需要在你的嘲笑提供这样的数据或功能。 例如,
var req = {};
req.url = "http://google.com"; // fake the Url
var res = {};
res.write = function(chunk, encoding) {
// fake the write method
};
var next = function(err) {console.log('lala')}
controller.get_user(req, res, next)
Answer 3:
我会尝试使用dupertest这一点。 这是我为便于控制测试的根本目的创建的,而不必旋转了一个新的服务器节点模块。
它使像节点模块的熟悉的语法request
或supertest
,但同样,无需旋转了一个服务器。
它运行了很多像赫克托上述建议,但像茉莉花一个测试框架集成,觉得有点更加无缝。
关于你的问题可能看起来像一个例子:
request(controller.get_user)
.params({id: user_id})
.expect(user, done);
或者更明确的手写版本:
request(controller.get_user)
.params({id: user_id})
.end(function(response) {
expect(response).toEqual(user);
done();
});
注:该示例假定user_id
和user
的某处定义,以及控制器的争夺,返回基于ID的用户。
编辑:看完上面的回答您的回复,我会承认的缺点是目前该模块不整合默认情况下,更强大的模拟请求或响应对象。 dupertest
使得超级易于扩展和添加属性都req
和res
,但默认情况下,他们是相当光秃秃的。
Answer 4:
如果你想使用真正的req
和res
对象,你必须向服务器发送请求的实际。 然而,这是比你想象的要容易得多。 有在快速大量的实例GitHub库 。 以下是测试req.route
var express = require('../')
, request = require('./support/http');
describe('req', function(){
describe('.route', function(){
it('should be the executed Route', function(done){
var app = express();
app.get('/user/:id/edit', function(req, res){
// test your controllers with req,res here (like below)
req.route.method.should.equal('get');
req.route.path.should.equal('/user/:id/edit');
res.end();
});
request(app)
.get('/user/12/edit')
.expect(200, done);
})
})
})
Answer 5:
有点老帖子,但我想给我的2美分。 要采取的方法取决于你是否正在做单元测试和集成测试。 如果你打算使用下来的supertest的路线,这意味着你正在运行的实际执行的代码,这意味着你在做集成测试。 如果这是你想做的事这种做法是好的。
但是,如果你正在做单元测试,你会嘲笑REQ和RES对象(和任何其他有关依赖)。 在下面的代码(为了简洁,删除不相关的代码),我嘲笑资源,并给予只是一个模拟实现JSON的方法,因为这是我需要为我的测试的唯一方法。
// SUT
kids.index = function (req, res) {
if (!req.user || !req.user._id) {
res.json({
err: "Invalid request."
});
} else {
// non-relevent code
}
};
// Unit test
var req, res, err, sentData;
describe('index', function () {
beforeEach(function () {
res = {
json: function (resp) {
err = resp.err;
sentData = resp.kids;
}
};
});
it("should return error if no user passed in request", function () {
req = {};
kidsController.index(req, res);
expect(err).to.equal("Invalid request.");
});
/// More tests....
})
文章来源: How to mock request and response in nodejs to test middleware/controllers?