【发布时间】:2019-08-03 05:45:49
【问题描述】:
TLDR:我的 api 与 curl 和 postman 一起工作正常,但在一个 put 请求中使用 chai-http 时测试失败,并出现错误“无法设置 headers after they are sent to the client”(所有其他 put 请求都有效)。我的所有集合都有一个通用的更新方法(附在下面),它适用于其他更新/放置请求。感谢您的帮助。
客户系列的 Mocha & Chai 测试
process.env.NODE_ENV = 'test';
const chai = require('chai');
const chaiHttp = require('chai-http');
const expect = chai.expect;
const c_paths = require('../constants/paths.js');
const app = require('../app.js');
chai.use(chaiHttp);
describe(c_paths.clients, () => {
it('It should create a new clients document', done => {
let req = {
test: true,
data: [
{
name: 'client 1',
contacts: [
{
name: 'client name 1',
mobile: 'client mobile 1',
email: 'client1@email.com',
},
],
address: ['client address 1'],
},
],
};
chai
.request(app)
.post(c_paths.clients)
.send(req)
.end((err, res) => {
expect(res).to.have.status(200);
expect(res.body.insertedCount).is.equal(
1,
'Number of inserted documents.',
);
expect(res.body.ops[0].name).is.equal(req.data[0].name);
expect(res.body.ops[0].contacts[0].name).is.equal(
req.data[0].contacts[0].name,
);
expect(res.body.ops[0].contacts[0].mobile).is.equal(
req.data[0].contacts[0].mobile,
);
expect(res.body.ops[0].contacts[0].email).is.equal(
req.data[0].contacts[0].email,
);
expect(res.body.ops[0].address[0]).is.equal(req.data[0].address[0]);
expect(res.body.ops[0].pause_updates).is.false;
expect(res.body.ops[0].pause_updates_toggle).is.false;
done();
});
});
it.('It should add a reccuring job', done => {
let req = {
test: true,
filter: {
name: 'client 1',
},
set: {
recurring_jobs: [
{
job_id: 'job id 1',
current_employee_id: 'employee id 1',
employee_scheduled_till: 'Apr 30 2019',
notes: ['note 1'],
duties: ['duty 1'],
repeat_in_days: 7,
time: '11:00:00', // Validation error switched to 10000
start_date: 'Mar 01 2019',
end_date: 'May 30 2019',
is_active: true,
},
],
},
};
chai
.request(app)
.put(c_paths.clients)
.send(req)
.end((err, res) => {
expect(res).to.have.status(200);
expect(res.body.ok).is.equal(1);
done();
});
});
it('It should delete one document', done => {
let req = {
test: true,
filter: {
name: 'client 1',
},
};
chai
.request(app)
.delete(c_paths.clients)
.send(req)
.end((err, res) => {
expect(res).to.have.status(200);
expect(res.body.n).is.equal(1, 'Number of documents removed');
done();
});
});
});
./routes/crud.js 中的更新方法。第 131 行的错误是 res.status(200)发送(结果);
function update(req, res, dbName, collectionName, joiSchema) {
var toValidate = '[';
var data = '{';
if (req.body.set) {
toValidate = toValidate.concat(JSON.stringify(req.body.set), ',');
data = data.concat('"$set":', JSON.stringify(req.body.set), ',');
}
if (req.body.inc) {
toValidate = toValidate.concat(JSON.stringify(req.body.inc), ',');
data = data.concat('"$inc":', JSON.stringify(req.body.inc), ',');
}
if (req.body.addToSet) {
let temp = JSON.stringify(req.body.addToSet);
temp = temp.replace('{"$each":[', '[');
temp = temp.slice(0, -1); // Removes $each for validation
toValidate = toValidate.concat(temp, ',');
data = data.concat('"$addToSet":', JSON.stringify(req.body.addToSet), ',');
}
if (req.body.unset) {
data = data.concat('"$unset":', JSON.stringify(req.body.unset), ',');
}
if (req.body.currentDate) {
toValidate = toValidate.concat(JSON.stringify(req.body.currentDate), ',');
data = data.concat(
'"$currentDate":',
JSON.stringify(req.body.currentDate),
',',
);
}
if (req.body.rename) {
data = data.concat('"$rename":', JSON.stringify(req.body.rename), ',');
}
if (req.body.pullAll) {
toValidate = toValidate.concat(JSON.stringify(req.body.pullAll), ',');
data = data.concat('"$pullAll":', JSON.stringify(req.body.pullAll), ',');
}
toValidate = toValidate.slice(0, -1); // Removes trailing comma
data = data.slice(0, -1);
toValidate = toValidate.concat(']');
data = data.concat('}');
Joi.validate(toValidate, joiSchema, function(err, value) {
if (err) {
res.send(err);
return;
}
});
MongoClient.connect(c_db.url, function(err, db) {
if (err) {
res.send(err);
db.close();
return;
}
const dbo = db.db(dbName);
const filter = req.body.filter == null ? '' : req.body.filter;
dbo
.collection(collectionName)
.updateMany(filter, JSON.parse(data), function(err, result) {
if (err) {
res.send(err);
db.close();
return;
}
res.status(200).send(result); //Error Line 131
db.close();
});
});
};
错误响应
错误 [ERR_HTTP_HEADERS_SENT]:发送后无法设置标头 给客户 在 ServerResponse.setHeader (_http_outgoing.js:482:11) 在 ServerResponse.header (./App/node_modules/express/lib/response.js:767:10) 在 ServerResponse.send (./App/node_modules/express/lib/response.js:170:12) 在 ServerResponse.json (./App/node_modules/express/lib/response.js:267:15) 在 ServerResponse.send (./App/node_modules/express/lib/response.js:158:21) 在 ./App/routes/crud.js:131:25 结果(./App/node_modules/mongodb/lib/utils.js:414:17) 在 session.endSession (./App/node_modules/mongodb/lib/utils.js:401:11) 在 ClientSession.endSession (./App/node_modules/mongodb-core/lib/sessions.js:129:41) 在 executeCallback (./App/node_modules/mongodb/lib/utils.js:397:17)
【问题讨论】:
-
当您连续两次触发请求时,您通常会看到诸如
Cannot set headers after they are sent to the client之类的错误。我建议您仔细查看期望,看看您是否正在这样做 -
您的调用堆栈正在执行
send, json, send, head, setHeader,这又回到了您的./App/routes/crud.js的第131 行,那么这说明了什么? -
@Keith,我已经编辑了问题以显示错误行,为方便起见,这里是 ./App/routes/crud.js 在 chai.request.end 的更新函数中的错误行调用 res.status(200).send(result);完毕();同样的方法也用于更新其他集合,并且这些测试通过没有问题。
标签: javascript node.js express chai