Unit testing private functions in JavaScript
For some time now I’ve been unit testing my JavaScript with qUnit. Not only good practice, it also saves you an incredible amount of time when it comes to crossbrowser testing your scripts. The only problem I was testing private functions that are hidden within closures.
The bulk of the functions you want to test are not (and should not be) accessible from the global scope. So what I used to do is add a function that would expose the private functions I wanted to test, test them, and if all went well I’d comment out the expose-function. A bit of a hassle really…
While I was working on the documentation for TinySort when I had an idea. In the qUnit test page I don’t load the script in the head but do it via an ajax request. Then I alter the script exposing the desired private functions and then start the test… piece of cake really…
Just view the source of the TinySort unit test.
Somewhere around line 22 you’ll see this:
$.ajax({
url:'scripts/jquery.tinysort.js'
,dataFilter: function(data) {
return data.replace(/$.tinysorts*=s*{/g,'$.tinysort={expose:function(){return{toLowerCase:toLowerCase,isNum:isNum,contains:contains};},');
}
,success: startTest
});
When using $.ajax() jQuery will automatically inject your code into the DOM. But with that property ‘dataFilter’ you can alter the result right before injection. So with a little regular expression I look for ‘$.tinysort = {‘ to append a function that exposes the private functions that need testing, which is nothing more than this:
function(){
return{
toLowerCase: toLowerCase
,isNum: isNum
,contains: contains
};
}
You can test this by calling up the console in both TinySort and it’s unit test and calling the expose function on both pages:
$.tinysort.expose()