Nikita
Nikita

Reputation: 6099

how to unit-test private methods in jquery plugins?

Perhaps this is a bit of a novice JQuery question but:

For example, looking at blockUI plugin, how can methods install, remove, reset get unit-tested?

To draw a parallel, in Java I would:

  1. create a BlockUI interface containing public methods only (by definition)
  2. create a BlockUIImpl class implementing the above interface. This class would contain install(), remove(), reset() methods that could be public, or (package) protected

So, I would unit-test the Impl but client programmers would interact with the plugin via BlockUI interface.

Upvotes: 13

Views: 2922

Answers (3)

Cross
Cross

Reputation: 1464

I came up with the same question and after navigating and finding answers that not really apply, here's what I ended up to solve a similar problem.

Problem: "I have a widget that has a behavior I want to test to ensure it's working as expected, some of the methods are called internally because they have to solve internal behavior, exposing them as public does not make sense because they wont be called from outside, testing the public methods means you wont test the internals of the widget, so finally what can I do?"

Solution: "Creata a test widget that exposes the methods you are interested in testing and use them in the qunit, here is the example:"

// Namespaces to avoid having conflicts with other things defined similarly
var formeditortest = formeditortest || {};
// widget that inherits from the container I want to test
$.widget( "app.testcontainer", $.app.container,  {
    executeDrop: function(drop, helper) {
       var self = this;
       self._executeDrop(drop, helper);
    }
});
// Test cases
formeditortest.testDropSimple = function(assert) {
   var container = $("<div />");
   container.testcontainer();
   container.testcontainer("drop", 0, 3);
   assert.equal(true, $(innerDiv.children()[0]).hasClass("droparea"));
});

QUnit.test(name, function( assert ) {
   formeditortest.testDropSimple(assert);
   formeditortest.testDropBottom(assert);
});

Using this method the inherited testcontainer could have the preparation required to test elements and then the qunit will handle the test, this solves my problem, hope this works for someone else that is having troubles to approach these kind of tests.

Critics? welcome to comment, I want to improve this if I'm doing something silly!!!

Upvotes: 0

Zero Distraction
Zero Distraction

Reputation: 1356

Code written inside a function in JavaScript, or closure as you called it, is not necessarily isolated from the outside of that function.

It is useful to know that functions have visibility of the scope in which they are defined. Any closure you create carries the scope, and therefore functions, of the code that contains it.

This simple example with a jQuery plugin and an artificial "namespace" might serve to prove this assumption:

// Initialise this only when running tests
my_public_test_namespace = function(){};

jQuery.fn.makeItBlue = function() {

    makeItBlue(this);

    function makeItBlue(object) {
        object.css('color','blue');
    }

    if(typeof my_public_test_namespace != "undefined") {
        my_public_test_namespace.testHarness = function() {
            return {
                _makeItBluePrivateFn: makeItBlue
            }
        };
    }
};

$("#myElement").makeItBlue(); // make something blue, initialise plugin

console.debug(my_public_test_namespace.testHarness()._makeItBluePrivateFn);

But don't forget you shouldn't really test privates. ;)

Upvotes: 2

Jani Hartikainen
Jani Hartikainen

Reputation: 43273

The same applies here as with any other language and testing privates: To test private methods, you should exercise them via the public interface. In other words, by calling your public methods, the private methods get tested in the process because the public methods rely on the privates.

Generally private methods are not tested separately from the public interface - the entire point is that they are implementation details, and tests should generally not know too much about the specifics of the implementation.

Upvotes: 13

Related Questions