Невозможно проверить отклоненное обещание после перехода на Angular 1.6.3

Недавно я обновил свое приложение с Angular 1.5 до 1.6.3 и начал получать сбои модульного теста Jasmine (с PhantomJS) вокруг кода, основанного на обещаниях, который я написал:

Возможно необработанное отклонение: брошено undefined

Читая вокруг, я вижу, что принятое решение - связать .then () с блоками .catch (), чтобы изящно обрабатывать отклонения.

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

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

Это функция, которую я пытаюсь протестировать (после добавления необходимых блоков catch)

public deleteSomething = (thing) => {
    return this.UserMessages.buildConfirmDialog().then(() => {
        this.someService.remove(thing)
            .then(() => {
                this.UserMessages.showToast('Something deleted');
            })
            .catch((error) => {
                //handle error
            });
    })
    .catch((error) => {
        //handle error
    });
}

А вот и тест:

var thing = {foo: 'bar'},
    deferredRemove,
    deferredConfirm,
    //Mock service below injected into controller later on before test are run
    UserMessages = {
        buildConfirmDialog: jasmine.createSpy('buildConfirmDialog').and.callFake(function() {
            deferredConfirm = $q.defer();
            return deferredConfirm.promise.catch(angular.noop);
        })
    };

//Inject and controller setup here...

    describe('When deleting something', function() {
        beforeEach(function() {
            deferredRemove = $q.defer();
            spyOn(someService, 'remove').and.returnValue(deferredRemove.promise.catch(angular.noop));
        });
        describe('and the user confirms the deletion', function() {
            beforeEach(function() {
                ctrl.deleteSomething(thing);
                deferredConfirm.resolve();
                deferredRemove.resolve();
                $rootScope.$apply();
            });
            it('should call remove on someService', function() {
                console.log('someService.remove.calls = ' + someService.remove.calls.count());
                expect(someService.remove).toHaveBeenCalled();
            });
        });
        describe('and the user cancels the deletion', function() {
            beforeEach(function() {
                someService.remove.calls.reset();
                vm.deleteSomething(thing);
                deferredConfirm.reject({});
                $rootScope.$apply();
            });
            it('should not call remove on someService', function() {
                console.log('someService.remove.calls = ' + someService.remove.calls.count());
                expect(someService.remove.calls.count()).toEqual(0);
            });
        });
    });

У меня не было .catch(angular.noop) частей до обновления до 1.6.3, и я наткнулся на несколько сообщений, предлагающих сделать это, чтобы сделать тесты счастливыми, что, безусловно, помогло мне преодолеть необработанную ошибку отклонения в моем тестовом прогоне.

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что для спецификации теста отклонения в моей службе не должно быть вызовов функции удаления, поэтому количество вызовов должно быть равно нулю, но оно продолжает выходить как 1. Я добавил строку чтобы сбросить вызовы в моем тесте, чтобы убедиться, что это не участвовало в предыдущем тесте (я знаю, что вызовы предназначены для сброса между тестами).

Этот тест работал нормально, когда я был на 1.5, так что это должно быть что-то из-за того, что мой код \ тест написан не так хорошо, как изменения в 1.6.x

Кто-нибудь может пролить свет на то, что здесь может происходить, пожалуйста?

Спасибо


person mindparse    schedule 11.03.2017    source источник


Ответы (2)


У меня не было .catch(angular.noop) частей до обновления до 1.6.3, и я наткнулся на несколько сообщений, предлагающих сделать это, чтобы сделать тесты счастливыми, что, безусловно, помогло мне преодолеть необработанную ошибку отклонения в моем тестовом прогоне .

Добавление .catch(angular.noop) определенно обработает необработанное отклонение.

Он преобразует отклоненное обещание в выполненное !!

Ваш тест не проходит правильно, потому что вы нарушили свой код.

Для получения дополнительной информации см. https://stackoverflow.com/a/42733408/5535245.


Изменения в $ q для AngularJS V1.6

сообщать об обещаниях с обратным вызовом без отклонения

Отклоненные обещания, не имеющие обратного вызова для обработки отклонения, сообщают об этом $exceptionHandler, чтобы их можно было зарегистрировать на консоли.

ПРЕРЫВАНИЕ ИЗМЕНЕНИЙ

Необработанные отклоненные обещания будут регистрироваться в $exceptionHandler.

Тесты, которые зависят от конкретного порядка или количества сообщений в $exceptionHandler, должны будут обрабатывать отчет об отклоненных обещаниях.

рассматривать допущенные ошибки как обычные отклонения

Раньше ошибки, выдаваемые обработчиками onFulfilled или onRejected обещания, обрабатывались немного иначе, чем обычные отклонения: они передавались $exceptionHandler() (помимо преобразования в отклонения).

Причина такого поведения заключалась в том, что неперехваченная ошибка отличается от обычного отклонения, поскольку она может быть вызвана, например, ошибкой программирования. На практике это оказалось запутанным или нежелательным для пользователей, поскольку ни встроенные обещания, ни какая-либо другая популярная библиотека обещаний не отличает выброшенные ошибки от обычных отклонений. (Примечание. Хотя такое поведение не противоречит спецификации Promises / A +, оно также не предписывается.)

Эта фиксация устраняет различие, пропуская вызов $exceptionHandler(), таким образом обрабатывая выданные ошибки как обычные отклонения.

Примечание. Если явно не отключено, возможно, необработанные отклонения все равно будут перехвачены и переданы $exceptionHandler(), поэтому ошибки, возникшие из-за ошибок программирования и не обработанные иным образом (с последующим onRejected обработчиком), не останутся незамеченными.

Для получения дополнительной информации см. Руководство разработчика AngularJS - переход с Версии 1.5–1.6

person georgeawg    schedule 11.03.2017

отключите возможное необработанное отклонение в этой конфигурации и повторите попытку.

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);
person hvojdani    schedule 11.03.2017
comment
Я забыл упомянуть, что видел эту опцию конфигурации, а также добавил в конфигурацию своего приложения - person mindparse; 11.03.2017