Angularjs 迁移到Angular 1.6.3后无法测试被拒绝的承诺

Angularjs 迁移到Angular 1.6.3后无法测试被拒绝的承诺,angularjs,jasmine,angular-promise,angularjs-1.6,Angularjs,Jasmine,Angular Promise,Angularjs 1.6,我最近将我的应用程序从Angular 1.5更新到1.6.3,并开始发现Jasmine单元测试失败(使用PhantomJS),原因是我编写的基于承诺的代码: 可能未处理的拒绝:未定义的抛出 环顾四周,我发现公认的解决方案是将.then()与.catch()块链接起来,以优雅地处理拒绝 我已经为我的一个源文件做了这项工作,我正在测试这个源文件,以证明它克服了错误 然而,它现在发现了另一个问题,即当在我的代码中调用承诺拒绝时,我正在测试的期望不再通过 这是我尝试测试的函数(在添加所需的catch块之

我最近将我的应用程序从Angular 1.5更新到1.6.3,并开始发现Jasmine单元测试失败(使用PhantomJS),原因是我编写的基于承诺的代码:

可能未处理的拒绝:未定义的抛出

环顾四周,我发现公认的解决方案是将.then()与.catch()块链接起来,以优雅地处理拒绝

我已经为我的一个源文件做了这项工作,我正在测试这个源文件,以证明它克服了错误

然而,它现在发现了另一个问题,即当在我的代码中调用承诺拒绝时,我正在测试的期望不再通过

这是我尝试测试的函数(在添加所需的catch块之后)

下面是测试:

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);
            });
        });
    });
在升级到1.6.3之前,我没有安装
.catch(angular.noop)
部件,并且遇到一些帖子建议这样做以使测试愉快,这当然有助于我克服测试运行中未处理的拒绝错误

我现在面临的问题是,对于拒绝测试规范,在我的服务中不应该调用remove函数,因此调用的数量应该是零,但它一直是1。我在测试中添加了重置调用的行,以确保它不是前一个测试的结果(我知道调用是在测试之间重置的)

当我在1.5上时,这个测试运行得很好,所以这一定是因为我的代码\测试的编写方式不能很好地处理1.6.x中的更改

有人能解释一下这里可能发生的事情吗


谢谢

通过此配置禁用可能未处理的拒绝,然后再次测试

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);

通过此配置禁用可能未处理的拒绝,然后再次测试

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);
在升级到1.6.3之前,我没有安装
.catch(angular.noop)
部件,并且遇到一些帖子建议这样做以使测试愉快,这当然有助于我克服测试运行中未处理的拒绝错误

添加
.catch(angular.noop)
肯定会处理未处理的拒绝

它将被拒绝的承诺转换为履行的承诺

您的测试正确地失败了,因为您破坏了代码

有关详细信息,请参阅


AngularJS V1.6对$q的更改 报告不拒绝回调的承诺 拒绝的承诺没有回调来处理拒绝报告 这将发送到
$exceptionHandler
,以便将它们记录到控制台

零钱

未处理的拒绝承诺将记录到
$exceptionHandler

取决于
$exceptionHandler
将需要处理拒绝的承诺报告

将抛出的错误视为常规拒绝 以前,承诺的
oncompleted
onRejected
处理程序中抛出的错误在 与常规拒收略有不同的方式: 它们被传递到
$exceptionHandler()
(除了转换为拒绝之外)

这种行为的理由是,未捕获的错误不同于常规的拒绝,正如 例如,它可能是由编程错误引起的。在实践中,这被证明是令人困惑的 或者对用户来说是不受欢迎的,因为本地promises和任何其他流行的promise库都不受欢迎 区分抛出的错误和常规拒绝。 (注意:虽然这种行为不违反法律,但也没有规定。)

此提交通过跳过对
$exceptionHandler()
的调用来消除区别,从而 将错误作为常规拒绝抛出

注意: 除非明确关闭,否则可能未处理的拒绝仍将被捕获并传递给
$exceptionHandler()
,因此由于编程错误而引发的错误不会以其他方式处理(使用 后续的
onRejected
handler)不会被忽略

有关更多信息,请参见

在升级到1.6.3之前,我没有
.catch(angular.noop)
部分,并且遇到一些帖子建议这样做以使测试愉快,这当然有助于我克服测试运行中未经处理的拒绝错误

添加
.catch(angular.noop)
肯定会处理未处理的拒绝

它将被拒绝的承诺转换为履行的承诺

您的测试正确地失败了,因为您破坏了代码

有关详细信息,请参阅


AngularJS V1.6对$q的更改 报告不拒绝回调的承诺 拒绝的承诺没有回调来处理拒绝报告 这将发送到
$exceptionHandler
,以便将它们记录到控制台

零钱

未处理的拒绝承诺将记录到
$exceptionHandler

取决于
$exceptionHandler
将需要处理拒绝的承诺报告

将抛出的错误视为常规拒绝 以前,承诺的
oncompleted
onRejected
处理程序中抛出的错误在 与常规拒收略有不同的方式: 它们被传递到
$exceptionHandler()
(除了转换为拒绝之外)

这种行为的理由是,未捕获的错误不同于常规的拒绝,正如 例如,它可能是由编程错误引起的。在实践中,这被证明是令人困惑的 或者对用户来说是不受欢迎的,因为本机和任何其他流行的