Как на самом деле сбросить ожидания $httpBackend?

Я пытался и пытался заставить это работать. документация в лучшем случае кратка:

resetExpectations(); — сбрасывает ожидания всех запросов, но сохраняет все внутренние определения. Обычно вы вызываете resetExpectations во время многоэтапного теста, когда хотите повторно использовать один и тот же экземпляр макета $httpBackend.

Каждый раз, когда вызывается мой второй запрос, мой результат всегда имеет данные первого результата. Посмотрите на эту скрипту http://jsfiddle.net/tbwn1gt0/2/, где я сбрасываю ожидания после первого сброса, затем установите новые ожидания/результат, затем снова выполните сброс, чтобы получить неверные данные.

// --- SPECS -------------------------
var url = '/path/to/resource';
var result = '';

describe('$httpBackend', function () {

    it("expects GET different results in subsequent requests", inject(function ($http, $httpBackend) {

        successCallback = function(data){
            result = data;            
        }
        // Create expectation
        $httpBackend.expectGET(url).respond(200, 'mock data');

        // Call http service
        $http.get(url).success(successCallback);

        // flush response
        $httpBackend.flush();
        console.log( result ); // logs 'mock data'

        // Verify expectations
        expect( result ).toContain('mock data'); // works as it should

        // reset the expectations
        $httpBackend.resetExpectations();

        // set the fake data AGAIN
        $httpBackend.expectGET(url).respond(200, 'doof the magic cragwagon');

        // get the service AGAIN
        $http.get(url).success(successCallback);
        expect( result ).toContain('doof'); // does not work, result is original result
        console.log( result ); // logs 'mock data'

    }));

});

// --- Runner -------------------------
(function () {
    var jasmineEnv = jasmine.getEnv();
    jasmineEnv.updateInterval = 1000;

    var htmlReporter = new jasmine.HtmlReporter();

    jasmineEnv.addReporter(htmlReporter);

    jasmineEnv.specFilter = function (spec) {
        return htmlReporter.specFilter(spec);
    };

    var currentWindowOnload = window.onload;

    window.onload = function () {
        if (currentWindowOnload) {
            currentWindowOnload();
        }
        execJasmine();
    };

    function execJasmine() {
        jasmineEnv.execute();
    }

})();

Другие вещи, которые я пробовал, включают добавление afterEach с помощью resetExpectations (помещение каждого запроса в новый оператор it). и множество других случайных попыток. Если он попытается изменить ожидаемый URL-адрес на что-то неожиданное, произойдет ошибка, как и должно быть, поэтому я знаю, что запросы обрабатываются по крайней мере через httpBackend.

Это дефект или я неправильно его реализую?


person FlavorScape    schedule 18.08.2014    source источник


Ответы (3)


.resetExpectations() работает так, как вы ожидали, но вы просто забыли сбросить http-запрос для второго.

// set the fake data AGAIN
$httpBackend.expectGET(url).respond(200, 'doof the magic cragwagon');

// get the service AGAIN
$http.get(url).success(successCallback);

$httpBackend.flush(); // flush the second http request here

expect( result ).toContain('doof'); // does not work, result is original result
console.log( result ); // logs 'mock data'

Пример JSFiddle: http://jsfiddle.net/4aw0twjf/

PS. На самом деле $httpBackend.resetExpectations() не нужен для вашего теста.

person runTarm    schedule 18.08.2014
comment
ах да, так что я могу заставить скрипку работать, но не мой реальный производственный код. Это была просто опечатка, так что скрипка работает. Я предполагаю, что моя проблема в том, что обещания в моем сервисном стеке не срабатывают должным образом. - person FlavorScape; 19.08.2014
comment
Чувак, у меня должно быть что-то еще - я сделал новую скрипку jsfiddle.net/L4Lpn60g/3 с $q.defer разрешает имитировать мой случай с производственным кодом, но он работает, в отличие от производственного кода =( поведение, которое я вижу, я не могу воспроизвести в скрипке. Похоже, что код обещания вызывается ДО того, как flush(). Какого черта? Думаю, мне понадобится немного времени, чтобы сделать скрипку, которая показывает такое же поведение. - person FlavorScape; 19.08.2014
comment
Может быть, вы могли бы показать свой код вокруг $q.defer(). Скрипка была бы отличной. - person runTarm; 19.08.2014

Ваш случай не требует пересмотра ожиданий. Вы можете изменить поведение ожидания вместо очистки и создания нового. "expectGET" (и другие методы) возвращает requestHandler, например:

// Create expectation
var expectationHandler = $httpBackend.expectGET(url).respond(200, 'mock data');

// Call http service, flush response, verify expectations

// Modify behavior
expectationHandler.respond(200, 'doof the magic cragwagon');

// Call http service ... AGAIN
person ArtemM    schedule 17.05.2017

Поскольку у вас есть несколько вызовов, я бы использовал это в конце каждого теста, чтобы убедиться, что все http-вызовы успешны expect($httpBackend.flush).not.toThrow();, что означает, что вам не нужно вызывать $httpBackend.flush(); для каждого http-вызова.

Кроме того, неплохо было бы добавить такой блок afterEach.

afterEach(function () {
    $httpBackend.verifyNoOutstandingExpectations();
});
person ipinak    schedule 16.12.2015