UPDATE 2-July-2013
Using the last approach with the wrapped anonymous function can introduce some strange testing behavior. If you expect a thrown error, but there is an error in the actual execution the test will pass, but will pass on any error and probably not the one you were expecting. I do two things, if its an error i am specifying i ensure the error text returned from the stub and the thrown error are the same. If it is from a third party library where i don't necessarily know the errors i will put some arbitrary value so that i know the passes are specific to the units i am testing. Example using sinon.js to stub some shizzle.
it('should return an error if the save fails', function(){
stubCall.restore();
stubCall = sinon.stub(Provider, 'save').callsArgWith(1, new Error('Save Error'));
(function(){
User.create(fakeUser, function(err, user){
if(err)
throw err;
});
}).should.throw("Save Error");
});
I am getting into Node.js and trying to do some Behaviour Driven Development(BDD) with Mocha and should.js (and sinon in there as well at some point).
One thing i am having problems with is testing errors returned by a call back, for instance this simple test:
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
Provider.execute(stubQuery, function (err) {
//should.not.exist(err);
should.have.property('message', 'Invalid Query Object');
});
});
with the function:
PostgresqlProvider.prototype.execute = function (query, cb) {
};
It doesn't matter what i try and test, the test always passes (should.exist, etc), and the only way i can get it to fail first is by adding cb(null); into the execute function, which kinda goes against what i am doing as i am trying to test before adding behaviour, not adding behaviour to fail a test.
I know i am doing some real newb mistake here, probably on a few levels but i am not grasping the testing of an error passed as a call back with is not thrown (which i am sure i could test easier)!
UPDATE
Using the code from Herman, i adjusted and that indeed words (the test is failing with no behavior defined)
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
Provider.execute(stubQuery, function (err) {
if (err) throw new Error(err);
}).should.throw();
});
issue now is i can't "catch" the error if sent in the callback to pass the test, the should.throw method doesn't get called, it just states that expected a throw to happen but didnt even though i am returning an error to the callback from my method. This could be down to scope but i am unsure if i should add some form of closure, and at what level.
UPDATE 2
Figured it out, i needed to wrap the call to the function inside a closure, not the callback (Doh!) and then place the assert (should.throw) at the end of the closure;
it('should return an error if you try and execute an invalid Query object', function () {
var stubQuery = {};
(function(){
Provider.execute(stubQuery, function (err) {
if (err)
throw err;
});
}).should.throw();
});