如何在 restify HTTP 处理程序中测试我的异步代码?
How can I test my asynchronous code in a restify HTTP handler?
我的 Restify 项目中有一个函数可以处理 HTTP GET 请求。经过一些处理后,它使用 Sequelize 找到我当前会话的用户实体。 User.findOne
函数 return 是一个承诺,根据该承诺的结果,我将发送 200 或 404 的 HTTP 响应。
static getMe(req, res, next) {
const userInfo = BaseController.getUserSession(req);
// hard to test this part
User.findOne({
where: {email: userInfo.email}
}).then(function(user) {
if (user) BaseController.respondWith200(res, user);
else BaseController.respondWith404(res, 'User not found.');
}, function(error) {
BaseController.respondWith404(res, error);
}).then(function() {
return next();
});
}
我已经尝试了几个不同的库来帮助测试,所以如果这是一个混乱的组合,我很抱歉。这是我用于测试的 beforeEach
函数:
const usersFixture = [
{id:2, email:'ozzy@osbourne.com', facebookId:54321, displayName: 'Ozzy Osbourne'},
{id:3, email:'zakk@wylde.com', facebookId:34521, displayName: 'Zakk Wylde'},
{id:4, email:'john@lennon.com', facebookId:12453, displayName: 'John Lennon'}
];
this.findOneSpy = sinon.spy(function(queryObj) {
return new Promise(function(resolve, reject) {
const user = usersFixture.find(function(el) { return el.email === queryObj.where.email });
if (user) resolve(user);
else resolve(null);
});
});
this.respondWith200Spy = sinon.spy(function(res, data) {});
this.respondWith400Spy = sinon.spy(function(res, error) {});
this.respondWith404Spy = sinon.spy(function(res, error) {});
this.controller = proxyquire('../../controllers/user-controller', {
'../models/user': {
findOne: this.findOneSpy
},
'./base-controller': {
respondWith200: this.respondWith200Spy,
respondWith400: this.respondWith400Spy,
respondWith404: this.respondWith404Spy
}
});
这是我的一项测试:
it('should return 200 with user data if user email matches existing user', function() {
// THIS FUNCTION IS NEVER HIT
this.respondWith200Spy = function(res, data) {
data.should.equal({id:4, email:'john@lennon.com', facebookId:12453, displayName: 'John Lennon'});
done();
};
const req = {session:{user:{email:'john@lennon.com'}}};
this.controller.getMe(req, this.res, this.nextSpy);
this.findOneSpy.should.have.been.called;
});
因为我们实际上并没有将回调传递给该函数,而且该函数实际上并没有 return 任何东西(只是在其他地方做异步事情),我不知道如何测试它使确定它工作正常。感谢任何帮助。
实际代码工作得很好。我只是想在项目中进行一些质量单元测试。谢谢!
我最终找到了一种使用 proxyquire 的方法。我只是 re-stubbed 我正在测试的控制器 class 并使 respondWith200
回调做出断言。然后我为 next
函数创建了一个新的间谍,它只调用 done
(它被传递到测试用例中)。我验证了所有代码都被命中了。
it('should return 200 with user data if user email matches existing user', function(done) {
const controller = proxyquire('../../controllers/user-controller', {
'../models/user': {
findOne: this.findOneSpy
},
'./base-controller': {
respondWith200: function(res, data) {
data.displayName.should.equal('John Lennon');
},
respondWith400: this.respondWith400Spy,
respondWith404: this.respondWith404Spy
}
});
const req = {grft_session:{user:{email:'john@lennon.com'}}};
const nextSpy = sinon.spy(function() {
done();
});
controller.getMe(req, this.res, nextSpy);
this.findOneSpy.should.have.been.called;
});
我的 Restify 项目中有一个函数可以处理 HTTP GET 请求。经过一些处理后,它使用 Sequelize 找到我当前会话的用户实体。 User.findOne
函数 return 是一个承诺,根据该承诺的结果,我将发送 200 或 404 的 HTTP 响应。
static getMe(req, res, next) {
const userInfo = BaseController.getUserSession(req);
// hard to test this part
User.findOne({
where: {email: userInfo.email}
}).then(function(user) {
if (user) BaseController.respondWith200(res, user);
else BaseController.respondWith404(res, 'User not found.');
}, function(error) {
BaseController.respondWith404(res, error);
}).then(function() {
return next();
});
}
我已经尝试了几个不同的库来帮助测试,所以如果这是一个混乱的组合,我很抱歉。这是我用于测试的 beforeEach
函数:
const usersFixture = [
{id:2, email:'ozzy@osbourne.com', facebookId:54321, displayName: 'Ozzy Osbourne'},
{id:3, email:'zakk@wylde.com', facebookId:34521, displayName: 'Zakk Wylde'},
{id:4, email:'john@lennon.com', facebookId:12453, displayName: 'John Lennon'}
];
this.findOneSpy = sinon.spy(function(queryObj) {
return new Promise(function(resolve, reject) {
const user = usersFixture.find(function(el) { return el.email === queryObj.where.email });
if (user) resolve(user);
else resolve(null);
});
});
this.respondWith200Spy = sinon.spy(function(res, data) {});
this.respondWith400Spy = sinon.spy(function(res, error) {});
this.respondWith404Spy = sinon.spy(function(res, error) {});
this.controller = proxyquire('../../controllers/user-controller', {
'../models/user': {
findOne: this.findOneSpy
},
'./base-controller': {
respondWith200: this.respondWith200Spy,
respondWith400: this.respondWith400Spy,
respondWith404: this.respondWith404Spy
}
});
这是我的一项测试:
it('should return 200 with user data if user email matches existing user', function() {
// THIS FUNCTION IS NEVER HIT
this.respondWith200Spy = function(res, data) {
data.should.equal({id:4, email:'john@lennon.com', facebookId:12453, displayName: 'John Lennon'});
done();
};
const req = {session:{user:{email:'john@lennon.com'}}};
this.controller.getMe(req, this.res, this.nextSpy);
this.findOneSpy.should.have.been.called;
});
因为我们实际上并没有将回调传递给该函数,而且该函数实际上并没有 return 任何东西(只是在其他地方做异步事情),我不知道如何测试它使确定它工作正常。感谢任何帮助。
实际代码工作得很好。我只是想在项目中进行一些质量单元测试。谢谢!
我最终找到了一种使用 proxyquire 的方法。我只是 re-stubbed 我正在测试的控制器 class 并使 respondWith200
回调做出断言。然后我为 next
函数创建了一个新的间谍,它只调用 done
(它被传递到测试用例中)。我验证了所有代码都被命中了。
it('should return 200 with user data if user email matches existing user', function(done) {
const controller = proxyquire('../../controllers/user-controller', {
'../models/user': {
findOne: this.findOneSpy
},
'./base-controller': {
respondWith200: function(res, data) {
data.displayName.should.equal('John Lennon');
},
respondWith400: this.respondWith400Spy,
respondWith404: this.respondWith404Spy
}
});
const req = {grft_session:{user:{email:'john@lennon.com'}}};
const nextSpy = sinon.spy(function() {
done();
});
controller.getMe(req, this.res, nextSpy);
this.findOneSpy.should.have.been.called;
});