3

I have a self-invoking function in a JavaScript file. Something like this:

com.renderer = (function(){

    render(data){

    }

    .....other functions 

    return{

        init : function(){
            $(document).ready(function(){
              jsonData = fetchFromServer();
              render(jsonData);
            });

         }
    }

})().init();

I am thinking of how to unit test this. I am using JSUnitTestDriver. If I could somehow inject jsonData to the render function from outside, that would be good, but that seems impossible to me.

Any suggestions or alternatives?

I really do not want to remove the self-invoking nature of the function. And does it really make sense to change what I consider good design for the sake of unit tests? (In this particular case, not in general.)

Note: I can't talk to a server while running tests.

Domenic
  • 110,262
  • 41
  • 219
  • 271
ChrisOdney
  • 6,066
  • 10
  • 38
  • 48

1 Answers1

1

The problem is that you are trying to unit test a singleton, and singletons are generally not considered good design.

Instead, I would consider something like the following:

function createRenderer(dataFetcher) {
    function render(data) {
    }

    // other functions

    return {
        init: function () {
            $(document).ready(function () {
                jsonData = dataFetcher();
                render(jsonData);
            });
        }
    };
}

// in your production code
com.renderer = createRenderer(fetchFromServer);
com.renderer.init();

// in your unit test
var renderer = createRenderer(function () {
    return { test: "data" };
});

renderer.init();
// run your tests against renderer.

This uses a technique called dependency injection, where the dependency on fetching JSON data is injected into your renderer, separating out that responsibility.

Domenic
  • 110,262
  • 41
  • 219
  • 271
  • Where is the datafetcher defined? My whole point of having this design is to avoid polluting the global namespace. Thanks. – ChrisOdney Nov 18 '11 at 11:36
  • 1
    The reason you didn't get an answer is because in order for something to be testable, you have to be able to get a handle on it - your design provides no handles. Once your code runs, its completely sealed up in its closure and there is nothing for your testing code to try to work on. In order to test this code you have to do what is suggested here and created some kind of reference. – Jon Hartmann Feb 29 '16 at 17:45