how to unit-test private methods in jquery plugins?

半世苍凉 提交于 2019-12-30 05:55:49

问题


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

  • proper jquery plugins are written inside a closure
  • thus only methods defining the plugin interface are accessible from the outside
  • sometimes (or many times) one may need helper methods that it doesn't make sense to expose as part of plugin interface (for example because they alter internal state).
  • how do those get unit-tested?

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.


回答1:


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.




回答2:


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




回答3:


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!!!



来源:https://stackoverflow.com/questions/5750279/how-to-unit-test-private-methods-in-jquery-plugins

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!