javascriptnode.jsunit-testingeventsnodeunit

Nodeunit testing event based async code


I've already posted a few question the past few days, which were too long (I'm guessing because I didn't receive any non cryptic feedback). I've tried to make this brief.

The following code uses a 'setup-complete' event to notify the nodeunit setUp command to run the tests. Test 1 passes, test 2 fails with

FAILURES: Undone tests (or their setups/teardowns): - event based async code - test2

Is there some mistake in my code? Is nodeunit a bad choice for testing event based code? Is my approach? Any advice appreciated. thanks

async_setup.js:

var
  events = require( 'events' ),
  setup  = new events.EventEmitter;

module.exports = function ( app, cb ) {
  setup.on( 'setup-complete', function () {
    cb();
  });
  setTimeout( function () {
    if ( app.result ) throw new Error( "AlreadyConfiguredAppError" );
    app.result = "app is configured";
    setup.emit( 'setup-complete', app.result );
  }, 5000 );
  return app;
};

test/test.js:

var
  nodeunit = require( 'nodeunit' ),
  async_setup = require( '../async_setup' );

exports[ 'event based async code' ] = nodeunit.testCase({
  setUp: function ( callback ) {
    this.app = {};
    async_setup( this.app, callback );
  },

  tearDown: function ( callback ) {
    delete this.app;
    callback();
  },

  'test1': function ( t ) {
    t.expect( 1 );
    t.ok( this.app.result !== undefined, 'app is configured' );
    t.done();
  },

  'test2': function ( t ) {
    t.expect( 1 );
    t.ok( this.app.result !== undefined, 'app is configured' );
    t.done();
  }
});

Solution

  • The problem ended up being that the event listeners setup weren't being destroyed between tests. I fixed the issue by modifying the setUp function to use proxyquire with the noPreserveCache flag set:

    var proxyquire = require( 'proxyquire' );
    ...
    
    setUp: function ( callback ) {
      this.app = {};
      proxyquire.noPreserveCache();
      var async_setup = proxyquire( '../async_setup', {} );
      async_setup( this.app, callback );
    }
    

    The error message in Webstorm had more info, with a stack trace to a nodeunit async module error:

    iterator(x.value, function (err, v) {
    Cannot read property 'value' of undefined
    

    When I stepped through the code I noticed that there were two event listeners setup even though I only set one in the test.

    Hope this helps someone else out there.