4

I am doing some async testing with nodeunit and I was wondering whether it is possible to tell nodeunit to not terminate test cases until test.done is called.

Basically this is how my test cases looks like right now:

exports.basic = testCase({

  setUp: function (callback) {
    this.ws = new WrappedServer();
    this.ws.run(PORT);
    callback();
  },

  tearDown: function (callback) {
    callback();
  },

  testFoo: function(test) { 
    var socket = ioClient.connect(URL);
    socket.emit('PING', 1, 1);
    socket.on('PONG', function() { 
      // do some assertion of course
      test.done();
    }); 
  }
});

The problem now is that PONG is not sent back quick enough for the test code to be executed. Any ideas?

xjq233p_1
  • 7,810
  • 11
  • 61
  • 107
  • That's what it already does. The test will not be complete until `test.done()` is called. You have a syntax error after `test.done()` though, is that on purpose? – loganfsmyth Feb 21 '12 at 01:47
  • @loganfsmyth actually that's not true. Running this code node will warn me that I have unfinished test cases. Nodeunit actually terminates rather than wait for test.done(); – xjq233p_1 Feb 21 '12 at 08:31
  • Sorry, I misunderstood your title as saying that it was proceeding to the next test before the first one was done, but what you meant is that it was exiting before the test was finished. Those are two different things. – loganfsmyth Feb 21 '12 at 14:59

4 Answers4

1

The problem is that nodeunit is not expecting any assertions, so it doesn't wait for them and terminates immediately. Count your assertions and call test.expect() in the beginning of the test.

exports.example = function(test) {
    // If you delete next line, the test will terminate immediately with failure.
    test.expect(1);

    setTimeout(function(){
        test.ok(true);
        test.done();
    }, 5000);       
};
Strix
  • 1,094
  • 1
  • 10
  • 18
  • 1
    It works for me :-) Make sure that the test is not interrupted before calling `test.done()`. That could be caused by unhandled exception. – Strix Nov 05 '13 at 22:13
1

I just had a very similar problem, hence I was browsing this question. In my case the server (analogous to your WrappedServer) was throwing an exception, causing the test to exit abruptly without hitting my event handler with test.done(). I think it is rather rude of nodeunit to swallow the exception without a peep.

I had to resort to the debugger to find the problem, which if you haven't done before, I can save you a web search: node --debug-brk node_modules/nodeunit/bin/nodeunit your_nodeunit_test.js

2wav
  • 148
  • 6
0

You probably want something like:

/** Invoke a child function safely and prevent nodeunit from swallowing errors */
var safe = function(test, x) {
  try { x(test); } catch(ex) {
    console.log(ex);
    console.log(ex.stack);
    test.ok(false, 'Error invoking async code');
    test.done();
  }
};

exports.testSomething = function(test){
  test.expect(1); // Prevent early exit
  safe(test, function(test) {
    // ... some async code here
  });
};
Doug
  • 32,844
  • 38
  • 166
  • 222
0

When nodeunit says "Undone tests", that means that the node process has exited without finishing all of the tests. To be clear, that doesn't mean that "PONG is not sent back fast enough", what it means is that there were no more handlers in the event loop. If there are no more handlers, then there is nowhere for a PONG event to come from, so it is not possible for the test to continue.

For example, if you ran something like this:

var s = require('http').createServer();
s.listen(80)

When you run listen, the server starts listening for incoming data, and is added to the event loop to check for incoming connections. If you only did createServer then no events will fire and your program will just exit.

Do you have a anything bound to an error event anywhere that might be making errors not show up?

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251