4

Code example shown here: https://gist.github.com/sebinsua/8118001

(There are three failures and two passes. I would like there to be four failures and one success.)

It's possible to catch AssertionErrors with mocha if thrown from normal functions, but as soon as the functions are called from within a supertest wrapped app, I no longer am able to detect them. This is annoying as I wanted to be able to inject certain assertions into my express app which I could then test. (I am testing a middleware with side-effects that I wish to test, if you can tell me how to mockup request and response objects that also solves my problem.)

Because I am able to access a spy, I know that it's nothing to do with the state being inaccessible.

However, I notice that node.js/express.js/supertest automatically convert uncaught exceptions to an error message in the response. Perhaps that is what is stopping them from being caught by the mocha test?

Edit

I just tested out the code to immediately below to see if this is a general http.createServer() problem. It isn't. This means something is happening at either connect, express.js, supertest or superagent levels. (These snippets of code only work half-of-the-time btw...)

var http   = require("http"),
    assert = require('assert');

describe('Really crazy test of assertions', function () {
    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        http.createServer(function (req, res) {
            console.log("On the server.");
            throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
            res.end("HEY");
        }).listen(port);

        setTimeout(function () {
            console.log("On the client.");
            http.get('http://localhost:' + port + '/', function (res) {
                console.log("Will I receive the error message on the client's side? No.");
                console.log(res);
            });
            done();
        }, 1000);
    });
});

It looks like an express problem (see below) - I noticed the AssertionError wasn't appearing in red text (like it would in the case of being picked up by Mocha.)

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

describe('Really crazy test of assertions', function () {

    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        app.get('/', function (req, res) {
            console.log("On the server.");
            throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
            res.end('HEY');
        }).listen(port);

        setTimeout(function () {
            console.log("On the client.");
            http.get('http://localhost:' + port + '/', function (res) {
                console.log("Will I receive the error message on the client's side? No.");
                console.log(res);
            });
            done();
        }, 1000);
    });
});

In short my question is, how do I get A to behave like B?

A

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

var port = Math.floor(Math.random() * 9999) + 1;
app.get('/', function (req, res) {
    console.log("On the server.");
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.send('HEY');
}).listen(8888);

B

var http   = require("http"),
    assert = require('assert');

http.createServer(function (req, res) {
    console.log("On the server.");
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.end("HEY");
}).listen(8888);

UPDATE

Line 192 of senchalab's connect at /lib/proto.js is where this is all going wrong. There is a try-catch and this passes my error into the next middleware which continues to do the same thing until either a 4-arity middleware handles it or there are no more middleware in which it runs some fallback code to automatically print to the screen and discard the exception...

I've no idea what I can do to get it to throw my error again, unless I am able to overwrite the handle method someway or other.

olive
  • 1,194
  • 1
  • 15
  • 34

1 Answers1

2

You ask:

However, I notice that node.js/express.js/supertest automatically convert uncaught exceptions to an error message in the response. Perhaps that is what is stopping them from being caught by the mocha test?

Yes, that's pretty much how HTTP servers work by default: exceptions that do not have any special meaning for the server software are transformed into status 500 responses. So if you want to test that the server has thrown an exception, you can record this fact yourself and use it later. For instance:

var http    = require("http"),
    express = require("express"),
    assert  = require('assert');

var app = express();

function handler (req, res) {
    throw new assert.AssertionError({ message: "Can I throw an assertion error? "} );
    res.end('HEY');
}

describe('Really crazy test of assertions', function () {
    it("cannot create a server which throws an assertion error", function (done) {
        var port = Math.floor(Math.random() * 9999) + 1;
        var caught;
        app.get('/', function catcher() {
            try {
                handler.apply(this, arguments);
            }
            catch (ex) {
                caught = ex;  // Capture it ...
                throw ex;     // ... and rethrow it.
            }
        }).listen(port);

        setTimeout(function () {
            http.get('http://localhost:' + port + '/', function (res) {
                // Act on the caught exception, if it exists.
                // This could be assert.equal or whatever.
                if (caught)
                    throw caught;
                done();
            });
        }, 1000);
    });
});

This is meant to illustrate the principle. The catcher function could be designed to be generic enough to work for a whole bunch of different tests.

Louis
  • 146,715
  • 28
  • 274
  • 320