Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Revealing Module Pattern - Unit Testing with Jasmine

After a brief romance with the revealing module pattern I've come to realise a set-back when it comes to unit-testing modules. I cannot however decide if it is my approach to testing a module or whether there is some form of work-around.

Consider the following code:

var myWonderfulModule = (function () {
  function publicMethodA (condition) {
    if(condition === 'b') {
      publicMethodB();
    }
  }

  function publicMethodB () {
    // ...
  }

  return {
    methodA : publicMethodA,
    methodB : publicMethodB
  }
}());

If I wanted to test (using Jasmine) the various paths leading through publicMethodA to publicMethodB. I might write a small test like so:

it("should make a call to publicMethodB when condition is 'b'", function() {
  spyOn(myWonderfulModule , 'publicMethodB');
  myWonderfulModule.publicMethodA('b');
  expect(myWonderfulModule.publicMethodB).toHaveBeenCalled();
});

If I understand correctly, there's a copy of publicMethodB within the closure that cannot be changed. Even if I change myWonderfulModule.publicMethodB afterwards:

myWonderfulModule.publicMethodB = undefined;

calling myWonderfulModule.publicMethodA will still run the original version of B.

The example above is of course simplified but there are plenty of scenarios I can think of where it would be convenient to unit test conditional paths through a method.

Is this a limitation of the revealing module pattern or simply a misuse of unit testing? If not what work-arounds are available to me? I'm considering moving to something like RequireJS or reverting back to non-modular code.

Any advice appreciated!

like image 589
backdesk Avatar asked Jun 14 '13 14:06

backdesk


People also ask

What is the revealing module pattern?

The Revealing Module pattern is a design pattern for Javascript applications that elegantly solves this problem. The central principle of the Revealing Module pattern is that all functionality and variables should be hidden unless deliberately exposed.

Is a design pattern which let you Organise your JavaScript code in modules and gives better code structure?

Revealing module pattern is a design pattern, which let you organise your javascript code in modules, and gives better code structure. It gives you power to create public/private variables/methods (using closure), and avoids polluting global scope (If you know how to avoid that).

Does Jasmine have a test runner?

Jasmine comes with an inbuilt test runner. Jasmine tests can run browser tests by including a simple SpecRunner. html file or by using it as a command line test runner supported for various languages like Nodejs, Python, Ruby, or (old way) by using Karma, a simple JavaScript test runner tool.


1 Answers

You cant test the intern methodes of a closure. And you also shouldn't spy on it. Think about about your module as a black box. You put something in and you get something out. All you should test is that the thing you get out of your module is the one that you expect.

Spying on methodes in your module makes not much sense. Think about it. You spy on it, the test passes. Now you change the functionality so it creates a bug, the test still passes cause the function is still called but you never mention the bug. If you just test the thing that cames out you dont need to spy on internal methodes cause, that they are called is implicite when the outcome of the module is what you expect.

So in your case there is no thing that goes in and nothing comes out. This makes not much sense but I believe that your module interacts with DOM or makes an ajax call. This are things that you can test (DOM) or you should spy on (ajax).

You should also make you self familiar with Inversion of Control and Dependency Injection. These are patterns that will make your modules much more easier to test.

like image 183
Andreas Köberle Avatar answered Nov 15 '22 16:11

Andreas Köberle