Как правильно модульный тест jQuery. ajax() обещает использовать Jasmine и/или Sinon?


у меня есть довольно простая функция, которая возвращает jQuery .ajax () обещание как таковое:

CLAW.controls.validateLocation = function(val, $inputEl) {
    return $.ajax({
        url: locationServiceUrl + 'ValidateLocation/',
        data: {
            'locationName': val
        },
        beforeSend: function() {
            $inputEl.addClass('busy');
        }
    }).done(function(result) {
        // some success clauses
    }).fail(function(result) {
        // some failure clauses
    }).always(function() {
        // some always clauses
    });
}

по большей части, этот новый интерфейс обещаний работает как мечта и устраняет пирамиды обратного вызова при использовании jQuery .Аякс() отличное. Тем не менее, я не могу для жизни меня выяснить, как правильно проверить эти обещания, используя Жасмин и/или Синон:

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

  2. при попытке использовать Жасмин или Синон шпион, чтобы шпионить за $.Аякс, шпион эффективно переписывает обещание, поэтому его done,fail, и always предложения больше не существуют в функции ajax, поэтому обещание никогда не разрешает и не выдает ошибку вместо

Я бы очень хотел пример или два, как проверить эти новые jQuery .ajax () обещает с вышеупомянутым тестирование библиотеки. Я довольно интенсивно прочесал сеть и на самом деле ничего не раскопал. Один ресурс, который я нашел, упомянул использование Жасмин.ajax, но я хотел бы избежать этого, если это возможно, поскольку Sinon предоставляет большую часть тех же возможностей из коробки.

4 55

4 ответа:

- Это не так уж сложно на самом деле. Достаточно вернуть обещание и решить его в соответствии с вашим делом.

например:

spyOn($, 'ajax').andCallFake(function (req) {
    var d = $.Deferred();
    d.resolve(data_you_expect);
    return d.promise();
});

для успеха, или

spyOn($, 'ajax').andCallFake(function (req) {
    var d = $.Deferred();
    d.reject(fail_result);
    return d.promise();
});

на провал.

для Jasmine 2.0 синтаксис немного изменился:

spyOn($, 'ajax').and.callFake(function (req) {});

метод .andCallFake () не существует в Jasmine 2.0

что-то в этом роде / с Синоном и jQuery deferreds

ajaxStub = sinon.stub($, "ajax");

function okResponse() {
  var d = $.Deferred();
  d.resolve( { username: "testuser", userid: "userid", success: true } );
  return d.promise();
};

function errorResponse() {
 var d = $.Deferred();
 d.reject({},{},"could not complete");
 return d.promise();
};

ajaxStub.returns(okResponse());
ajaxStub.returns(errorResponse());

вот более простой подход с помощью только javascript.

quoteSnapshots: function (symbol, streamId) {
                var FakeDeferred = function () {
                    this.error = function (fn) {
                        if (symbol.toLowerCase() === 'bad-symbol') {
                            fn({Error: 'test'});
                        }
                        return this;
                    };
                    this.data = function (fn) {
                        if (symbol.toLowerCase() !== 'bad-symbol') {
                            fn({});
                        }
                        return this;
                    };
                };

                return new FakeDeferred();
            }

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

решение, данное @ggozad не будет работать, если вы используете такие вещи, как .complete().

но, ура, Жасмин сделал плагин, чтобы сделать именно это:http://jasmine.github.io/2.0/ajax.html

beforeEach(function() {
  jasmine.Ajax.install();
});

afterEach(function() {
  jasmine.Ajax.uninstall();
});

//in your tests
expect(jasmine.Ajax.requests.mostRecent().url).toBe('/some/cool/url');