I'm writing my first tests for a Mongodb database using should.js, and need a way to force errors in various functions that make database calls.
I've spent a little time exploring how Rewire.js might help, but am still new enough to Mongo that I'm not sure what I should 'rewire' to force database errors.
Perhaps there is a better way to write the functions to trigger errors during testing.
I appreciate any ideas.
For what it's worth, this is what I've come up with and would appreciate any comments. I didn't have long to write this up, so please forgive any typos.
The typical layout of a function with an embedded async call is usually something like:
function my_function(callback) {
async_call(function(err, doc) {
if (err) {
//Do error prep such as with VError
callback(err, null);
} else {
//Do success prep such as:
var result = doc.property;
callback(null, result);
}
});
}
The problem is having a great way to test the code in the error path. There are solutions like Rewire which do well if, by changing the value of a global variable you can trigger the desired error, but its hard to find a way to break Mongodb calls by rewriting a global.
My solution was to: 1) rewrite my async functions that I need to "break" in order to test
my_function = {
get: function(callback) {
async_call(function(err, doc) {
my_function.manage_return(err, doc, callback);
});
},
manage_return: function(err, doc, callback) {
if (err) {
//Do error prep such as with VError
callback(err, null);
} else {
//Do success prep such as:
var result = doc.property;
callback(null, result);
}
});
}
2) During testing, if I need to force an error, I just rewrite get:
var original_get = my_lib.my_function.get; //NO parenthesis!!!
my_lib.my_function.get = function(callback) {
my_lib.my_function.manage_return("This is a forced error", null, callback);
};
Later if I need to restore the function:
my_lib.my_function.get = original_get;
I've actually written a constructor that makes the rewrite/restore procedure much more streamlined, that I'd be glad to post if anyone is interested.
I did try using Rewire to handle the rewrite/restore procedure without success. Worse, "rewritten" code can't be single-stepped.
PROS
*Doesn't use eval
*Single step debugging (at least in WebStorm) works
*Can force any error at will
*Doesn't alter the function signature
*Gives ability to force a specific function to fail, which is a huge help when testing error handling of larger functions that rely on several subordinate functions
CONS
*I have to rewrite all my async functions as objects with get and mange_return
*If the function is in a module, I have to export the function in order to rewrite/restore it
Thoughts?