我有一个这样的路由处理程序:
router.route('/sipprovider/:sipprovider_id/phonelist')
.post((req, res) => {
const body = req.body;
if (typeof body.phones === 'undefined') {
return res.status(400).json({
success: false,
error: { message: 'Invalid input' }
});
}
if (!Array.isArray(body.phones) || body.phones.length === 0) {
return res.status(400).json({
success: false,
error: { message: 'Invalid input' }
});
}
let i = body.phones.indexOf('');
while (i >= 0) {
body.phones.splice(i, 1);
i = body.phones.indexOf('');
}
body.phones.map((phone) => {
if (typeof phone !== 'string') {
return res.status(400).json({
success: false,
error: { message: 'Invalid input' }
});
}
});
const SipProvider = new SipProviderModel(db, logger);
SipProvider.pushPhoneList(req.params.sipprovider_id, body.phones)
.then((result) => {
if (result) {
return res.json({ success: true });
}
return res.status(404).json({
success: false,
error: { message: 'Sip provider not found' }
});
})
.catch((error) => res.status(400).json({
success: false,
error: { message: error }
}));
});
pushPhoneList
的{{1}}函数是一个承诺。我写了几个测试:
SipProvider
所有这些都通过,但记录器在包含describe('POST', () => {
let id;
beforeEach(() => SipProvider.create(data).then((result) => id = result._id));
it('Should return 200 if successful', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: ['02873000050'] })
.end((err, res) => {
expect(res.status).to.equal(200);
expect(res.body.success).to.equal(true);
return done();
});
});
it('Should return 200 if successful', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: ['02873000050', ''] })
.end((err, res) => {
expect(res.status).to.equal(200);
expect(res.body.success).to.equal(true);
return done();
});
});
it('Should return 400 if input is invalid (undefined phones)', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.end((err, res) => {
expect(res.status).to.equal(400);
expect(res.body.success).to.equal(false);
expect(res.body.error.message).to.equal('Invalid input');
return done();
});
});
it('Should return 400 if input is invalid (not an array)', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: '02873000050' })
.end((err, res) => {
expect(res.status).to.equal(400);
expect(res.body.success).to.equal(false);
expect(res.body.error.message).to.equal('Invalid input');
return done();
});
});
it('Should return 400 if input is invalid (empty list)', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: [] })
.end((err, res) => {
expect(res.status).to.equal(400);
expect(res.body.success).to.equal(false);
expect(res.body.error.message).to.equal('Invalid input');
return done();
});
});
it('Should return 400 if input is invalid (not an array of string)', (done) => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: ['02873000050', {}] })
.end((err, res) => {
expect(res.status).to.equal(400);
expect(res.body.success).to.equal(false);
expect(res.body.error.message).to.equal('Invalid input');
return done();
});
});
it('Should return 404 if not found', (done) => {
SipProvider.delete(id).then(
() => {
chai.request(app)
.post('/sipprovider/' + id + '/phonelist')
.set('Authorization', token)
.send({ phones: ['02873000050'] })
.end((err, res) => {
expect(res.status).to.equal(404);
expect(res.body.success).to.equal(false);
expect(res.body.error.message).to.equal('Sip provider not found');
return done();
});
});
});
afterEach(() => SipProvider.delete(id));
});
的最后一个测试中记录了一些警告
我还没有理解为什么路由处理程序中的最终catch块被调用。我想只有当promise函数被拒绝时才会出现catch
答案 0 :(得分:3)
首先,在此代码中:
body.phones.map((phone) => {
if (typeof phone !== 'string') {
return res.status(400).json({
success: false,
error: { message: 'Invalid input' }
});
}
});
您最多可以多次拨打res.status()
。这很容易导致"在发送后无法设置标头"问题。这里的问题是return
仅从.map()
回调返回。它不会阻止.map()
中的其他回调,并且在该块执行后它不会阻止其余代码,这也会导致发送另一个响应。
您可以通过执行以下操作来解决此问题:
if (!body.phones.every(phone => typeof phone === 'string')) {
return res.status(400).json({
success: false,
error: { message: 'Invalid input' }
});
}
这将贯穿所有body.phones
项,测试它们是否都是正确的类型,然后,在循环外,如果它们不是所有正确的类型,那么它将return
。这只会发送一个响应,并将从外部函数返回,停止进一步执行。