lukas.pukenis
lukas.pukenis

Reputation: 13597

Javascript Module pattern - how to reveal all methods?

I have module pattern done like this:

var A = (function(x) {
   var methodA = function() { ... }
   var methodB = function() { ... }
   var methodC = function() { ... }
   ...
   ...
   return {
      methA: methodA,
      methB: methodB
   }
})(window)

This code let's me call only methA and methB() on A which is what I want and what I like. Now the problem I have - I want to unit test it with no pain ot at least with minimal efforts.


First I though I can simply return this but I was wrong. It returns window object.(can someone explain why?).

Second - I found solution somewhere online - to include this method inside my return block:

__exec: function() {
    var re = /(\(\))$/,
        args = [].slice.call(arguments),
        name = args.shift(),
        is_method = re.test(name),
        name = name.replace(re, ''),
        target = eval(name);
    return is_method ? target.apply(this, args) : target;
}

This method let's me call the methods like this: A.__exec('methA', arguments); It is almost what I want, but quite ugly. I would prefer A.test.methA() where test would never be used in production code - just for revealing private methods.


EDIT I see people telling me to test the big thing instead of the small parts. Let me explain. In my opinion API should reveal only the needed methods not a bunch of internal functions. The internals because of their small size and limited functionality are much easier to test then test the whole thing and guess which part gone wrong.

While I may be wrong, I would still like to see how I could return references to all the methods from the object itself :).

Upvotes: 3

Views: 1399

Answers (2)

Max Tkachenko
Max Tkachenko

Reputation: 504

Answer to your first question(you return this, but it returns window, not the object you wanted): in javascript this inside the function returns global object unless this function is a method of the object.

Consider next examples:

1) this points to the global object ():

function(){
   return this;
}

2) this points to the object:

var obj = {
    value: "foo",
    getThisObject: function(){
        return this;
    }
}

Your case is example #1, because you have a function, that returns an object. This function is not a method of any object.

The best answer to your second question is to test only public methods, but if that is so important for you, I can propose next:

create your modules dynamically on server side.

How it works:

  • create separate scripts for functionality you want;
  • create tests for these separate scripts;
  • create method that will combine scripts into one however you want;
  • to load script, reference to the combining scripts method.

Hopefully, it can solve your problem. Good luck!

Upvotes: 2

Mitja Gustin
Mitja Gustin

Reputation: 1781

Why not use namespaces to add your modules and public methods to js engine. Like this:

window['MyApp']['MODULE1'] = { "METHOD1" : {}, "METHOD2" : {}}; 

I write modules like this Sample module in JavaScript.

And test it like this: Simple unit testing in JavaScript

The use of eval() is generally not good idea.

Upvotes: 0

Related Questions