Как единично тестировать частные методы в jquery-плагинах?

Возможно, это немного новый вопрос JQuery, но:

  • правильные плагины jquery записываются внутри закрытия
  • таким образом, только методы, определяющие интерфейс плагина, доступны снаружи
  • иногда (или много раз) могут потребоваться вспомогательные методы, которые не имеют смысла раскрывать как часть интерфейса плагина (например, потому что они изменяют внутреннее состояние).
  • Как те, кто получает модульное тестирование?

Например, глядя на blockUI плагин, как можно установить методы, удалить, reset получить модульное тестирование?

Чтобы нарисовать параллель, в Java я бы:

  • создать интерфейс BlockUI, содержащий только общедоступные методы (по определению)
  • создать класс BlockUIImpl, реализующий вышеуказанный интерфейс. Этот класс будет содержать методы install(), remove(), reset(), которые могут быть общедоступными или (пакетными) защищенными

Итак, я бы тестировал Impl, но клиентские программисты могли бы взаимодействовать с плагином через интерфейс BlockUI.

Ответ 1

То же самое относится и к любому другому языку и тестированию частных лиц. Чтобы проверить частные методы, вы должны использовать их через открытый интерфейс. Другими словами, вызывая ваши общедоступные методы, частные методы проходят тестирование в процессе, потому что публичные методы полагаются на рядовых.

Обычно частные методы не тестируются отдельно от открытого интерфейса - все дело в том, что они являются деталями реализации, и тесты обычно не слишком много знают о специфике реализации.

Ответ 2

Код, написанный внутри функции в JavaScript или закрытие, как вы ее называли, не обязательно изолирован от внешней части этой функции.

Полезно знать, что функции имеют видимость области, в которой они определены. Любое замыкание, которое вы создаете, переносит область действия и, следовательно, функции кода, который ее содержит.

Этот простой пример с плагином jQuery и искусственным "пространством имен" может служить доказательством этого предположения:

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

Но не забывайте, что вы не должны действительно проверять рядовых.;)

Ответ 3

Я столкнулся с одним и тем же вопросом и после навигации и поиска ответов, которые на самом деле не применяются, вот что я решил решить подобную проблему.

Проблема: "У меня есть виджет с поведением, который я хочу протестировать, чтобы обеспечить его работу как ожидалось, некоторые из методов называются внутренне, потому что они должны решать внутреннее поведение, раскрывая их как общедоступные, не имеет смысла, потому что они не будут вызваны извне, тестирование общедоступных методов означает, что вы не будете проверять внутренности виджета, так что, наконец, что я могу сделать?"

Решение: "Creata - тестовый виджет, который предоставляет методы, которые вас интересуют в тестировании, и использовать их в qunit, вот пример:"

// 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);
});

Используя этот метод, унаследованный тестовый контейнер может иметь подготовку, необходимую для тестирования элементов, а затем qunit будет обрабатывать тест, это решает мою проблему, надеюсь, что это работает для кого-то другого, у которого есть проблемы, чтобы подходить к этим типам тестов.

Критики? добро пожаловать, чтобы прокомментировать, я хочу улучшить это, если я делаю что-то глупое.