3

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 :).

lukas.pukenis
  • 13,057
  • 12
  • 47
  • 81
  • 4
    you dont unit test private methods or you dont make them private. that's simple. – mpm Mar 18 '13 at 15:33
  • 1
    @mpm private methods are code too so they need to be tested out too. – lukas.pukenis Mar 18 '13 at 15:34
  • 2
    This is not good idea. Private methods are privite, you don't have to make them public. Test your public methods, they depend on private so testing public should also cover this. – dfsq Mar 18 '13 at 15:35
  • possible duplicate of [How to unit test 'private' utility funcion in nodejs](http://stackoverflow.com/questions/15322354/how-to-unit-test-private-utility-funcion-in-nodejs) – Bergi Mar 18 '13 at 16:53
  • @lukas.pukenis then make it public , what's so complicated about it ? you want to access something, make it public. You dont want then make it private. You can use composition to make something public private inside another object. I fail to understand what is the problem here. You just cant have it both ways, that's all. And as stated in the other question (upper) , TDD is about testing contracts. TDD doesnt care about private. – mpm Mar 18 '13 at 17:11
  • @mpm, the problem is that I inherited very big codebase and simply want to minimize my efforts :) I find no problem to reveal the functions as public, but that would involve a lot of manual work. – lukas.pukenis Mar 18 '13 at 17:22

2 Answers2

2

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!

Max Tkachenko
  • 504
  • 1
  • 6
  • 17
0

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.

Mitja Gustin
  • 1,723
  • 13
  • 17
  • You might be right of eval() but I don't see a problem with it. It's a language construct which helps in certain cases. – lukas.pukenis Mar 19 '13 at 08:50