Question seems to be a duplicate but I have been working to solve this from last 3 hours. Basically I'm using supertest
& mocha
to test my API.
I'm unable to understand which promise is not getting resolved.
app.post('/todos', (req, res) => {
var todo = new Todo({
text : req.body.text
});
todo.save().then( (doc) => {
res.status(200).send(doc)
}, (e) => {
res.status(400).end(e);
});
});
Following is the test I have written:
const expect = require('expect');
const request = require('supertest');
var {app} = require('./../server');
var {Todo} = require('./../models/todo');
// Setup database
beforeEach((done) => {
Todo.remove({})
.then(() => done())
.catch((e)=> done(e));
});
describe('Post /todos', () => {
it('should create a new todo', (done) => {
var text = 'Testing text';
// supertest to get, post
request(app)
.post('/todos')
.send({text}) // Automatic conversion to json - ES6
.expect(200) // assertions
.expect((res) => { // custom parsing
expect(res.body.text).toBe(text);
})
.end((err, res) => { // done directly accepted, but rather let's be more precise now - check mongodb
if (err) {
return done(err);
}
Todo.find()
.then((todos) => {
expect(todos.length).toBe(1);
expect(todos[0].text).toBe(text);
done();
})
.catch((e) => done(e));
});
});
});
Please help to resolve this. Here's the whole error msg:
mocha server/**/*.test.js Listening on port: 3000 Post /todos (node:1882) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: First argument must be a string or Buffer (node:1882) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 1) should create a new todo 0 passing (2s) 1 failing 1) Post /todos should create a new todo: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
The end
function in express only accepts a string or a buffer, not an object (see https://expressjs.com/en/api.html#res.end and https://nodejs.org/api/http.html#http_response_end_data_encoding_callback).
However, it looks like todo.save()
calls reject
with an object, meaning that e
causes the TypeError
. Because this is an error with catching a promise rejection, the error is wrapped in the Unhandled Promise Rejection
warning.
Assuming the e
is { message: "First argument must be a string or Buffer" }
, the new code could be:
todo.save().then( (doc) => {
res.status(200).send(doc)
}, (e) => {
res.status(400).end(e.message);
});
The reason that the todo.save()
promise is being rejected is probably because the text
in the todo appears to be undefined. This is the JSON that is assigned to req
:
{
text: 'Testing text'
}
However, it should be this:
{
body: {
text: 'Testing text'
}
}
The testshould then be fixed if you change the send to this:
.send({ body: { text }) // Automatic conversion to json - ES6