I have this code using supertest and mocha:
import request from 'supertest';
//....
var newGame;
describe('Creating game', function() {
beforeEach(function(done) {
request(app)
.post('/api/games')
.send({
owner: 'Mr. X',
})
.expect(201)
.expect('Content-Type', /json/)
.end((err, res) => {
if (err) {
return done(err);
}
newGame = res.body;
done();
});
});
describe('the created game', function() {
it('should name the specified owner', function() {
newGame.owner.should.equal('Mr. X');
});
...
})
});
When the server code throws some exception (e.g. accessing properties of an undefined object) I get this stack trace
Error: expected 201 "Created", got 500 "Internal Server Error"
at Test._assertStatus (D:\Codes\theApp\node_modules\supertest\lib\test.js:232:12)
at Test._assertFunction (D:\Codes\theApp\node_modules\supertest\lib\test.js:247:11)
at Test.assert (D:\Codes\theApp\node_modules\supertest\lib\test.js:148:18)
at Server.assert (D:\Codes\theApp\node_modules\supertest\lib\test.js:127:12)
at emitCloseNT (net.js:1521:8)
instead of the actual error that says something like "accessing properties of undefined". How can I get the actual error?
There are probably a lot of ways to tackle this, but I don't believe mocha or supertest have access to the actual error that caused the 500 to occur.
What are you using to create app
? If it's Express, for example, error-handling middleware can be added during testing which causes any 500-inducing errors to be logged to the console.
You can have your test code listen for the uncaughtException event that the process will raise. As long as the express app does all of its processing in the same process as the test harness any unhandled exception in the process will be send to the process uncaughtException event handler. Now, here's where it can get a bit tricky. Since, it's event based it can be fired at any time there is an unhandled exception. So, if you want to be more explicit and you only want to handle exceptions from the system under test, you will need to add/remove the listener before/after the system under test code is ran. Here's your example updated to listen for an unhandled exception.
import request from 'supertest';
//....
var newGame;
describe('Creating game', function() {
beforeEach(function(done) {
var unhandledException = undefined;
var unhandledExceptionCallback = function(err) {
unhandledException = err;
}
process.on('uncaughtException', unhandledExceptionCallback);
request(app)
.post('/api/games')
.send({
owner: 'Mr. X',
})
.expect(201)
.expect('Content-Type', /json/)
.end((err, res) => {
process.removeListener('uncaughtException', unhandledExceptionCallback);
if (unhandledException !== undefined){
return done(unhandledException);
} else if (err) {
return done(err);
}
newGame = res.body;
done();
});
});
describe('the created game', function() {
it('should name the specified owner', function() {
newGame.owner.should.equal('Mr. X');
});
...
})
});
I think this is an api design issue. An api should provide a client with useful error information, especially if differences in client input are causing the server side error.
Your can do this in your endpoint or globally in some middleware.