Don't rip your hair out when Vows tells you "Errored callback not fired" - try this one weird trick instead

; Date: Wed Jan 07 2015

Tags: Node.JS »»»» Node.js Testing

When your vows.js based tests for a Node.js application says "Errored » callback not fired" -- well, it can be very confusing. In my case the code clearly handled all paths ensuring the Vows callback would be called. No matter how many tweaks I performed to try and catch some possible error in test or code, I couldn't figure out what caused this problem. But after some yahoogling, the answer was not only difficult to find, but surprisingly simple.

To review, an asynchronous test in Vows.js is supposed to follow this pattern:

{ topic: function () {
    fs.stat('~/FILE', this.callback);
  },
  'can be accessed': function (err, stat) {
    assert.isNull   (err);        // We have no error
    assert.isObject (stat);       // We have a stat object
  },
  'is not empty': function (err, stat) {
    assert.isNotZero (stat.size); // The file size is > 0
  }
}

The code this.callback is a little piece of magic that Vows uses to capture the data provided by the asynchronous callback. It's supposed to be used in the typical pattern for callbacks: function(err, other, arguments) and Vows will dutifully capture everything and do appropriate stuff with it.

What if your code needs to make a couple layers of asynchronous calls? A little trick to consider is that this won't have the same value for subsequent layers of asynchronous calls as it has at the first layer. Hence, you should do something like

{ topic: function () {
    var that = this;
    fs.stat('~/FILE', function(err, stats) {
        if (err) that.callback(err);
        else {
            doSomethingElse(arg, arg2, function(err2, other, data) {
                if (err2) that.callback(err2);
                else that.callback(null, other, data);
            });
        }
    });
  },
...
}

The point is to ensure you call callback function provided by Vows.

In my test, I'd done that, but still it told me the callback wasn't being triggered. It seems from what I found while searching that other people have also beat their heads against this particular wall.

What I eventually discovered was deceptively simple. The problem is that Vows does something to the normal logging output circumventing its display, I suppose so the pretty report can be printed on the console? What's necessary is to add this code to your test case.

process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err.stack);
});

The problem I had was that - indeed - the callback wasn't being triggered, and that's because of an error buried inside the code that was being tested. That error wasn't being caught and Vows also ensured the information didn't get printed while still causing the test case to fail mysteriously.

The error in my code isn't important to this story. What IS important is that as soon as the test was run with this code, the error was immediately obvious and immediately fixable.

About the Author(s)

(davidherron.com) David Herron : David Herron is a writer and software engineer focusing on the wise use of technology. He is especially interested in clean energy technologies like solar power, wind power, and electric cars. David worked for nearly 30 years in Silicon Valley on software ranging from electronic mail systems, to video streaming, to the Java programming language, and has published several books on Node.js programming and electric vehicles.

Books by David Herron

(Sponsored)