迁移到Angular 1.6.3后无法测试被拒绝的承诺 [英] Unable to test a rejected promise after migrating to Angular 1.6.3

查看:196
本文介绍了迁移到Angular 1.6.3后无法测试被拒绝的承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


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


阅读我看到接受的解决方案是链.then( )使用.catch()块来优雅地处理拒绝。



我为我测试的一个源文件做了这个,以证明这已经超过了错误确实如此。



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



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

  public deleteSomething =(thing)=> {
返回this.UserMessages.buildConfirmDialog()。then(()=> {
this.someService.remove(thing)
.then(()=> {
this.UserMessages.showToast('Something deleted');
})
.catch((error)=> {
// handle error
});
})
.catch((错误)=> {
//处理错误
});
}

这是测试:

  var thing = {foo:'bar'},
deferredRemove,
deferredConfirm,
//以下注入控制器的模拟服务在测试之前运行
UserMessages = {
buildConfirmDialog:jasmine.createSpy('buildConfirmDialog')。and.callFake(function(){
deferredConfirm = $ q.defer();
return deferredConfirm.promise.catch(angular.noop);
})
};

//在这里注入和控制器设置...

describe('当删除某些东西'时,function(){
beforeEach(function(){
deferredRemove = $ q.defer();
spyOn(someService,'remove')。and.returnValue(deferredRemove.promise.catch(angular.noop));
});
describe('和用户确认删除',function(){
beforeEach(function(){
ctrl.deleteSomething(thing);
deferredConfirm.resolve();
deferredRemove.resolve();
$ rootScope。$ apply();
});
it('应该在someService上调用remove',function(){
console。 log('someService.remove.calls ='+ someService.remove.calls.count());
expect(someService.remove).toHaveBeenCalled();
});
}) ;
描述('和用户取消删除', function(){
beforeEach(function(){
someService.remove.calls.reset();
vm.deleteSomething(thing);
deferredConfirm.reject({});
$ rootScope。$ apply();
});
it('不应该在someService上调用remove',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上时,这个测试运行得很好,所以这必须与我的code \ test编写的方式不符合1.6.x中的变化。



有人可以了解这里可能会发生什么吗?



谢谢

解决方案

在升级到1.6.3之前,我没有 .catch(angular.noop)部分,并且发现了一些建议这样做的帖子为了让测试变得愉快,这对我在测试运行中遇到未处理的拒绝错误肯定有帮助。



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



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



由于您的代码损坏,您的测试正确失败。



有关详细信息,请参阅 Catch方法无法使用$ http获取请求






AngularJS V1.6的$ q变化



报告承诺非拒绝回拨




拒绝承诺没有回调来处理拒绝报告
这个到 $ exceptionHandler 所以他们可以登录到控制台。



BREAKING CHANGE



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



测试取决于 $ exceptionHandler中的特定订单或消息数量
将需要处理被拒绝的承诺报告。




将抛出的错误视为常规拒绝




以前,承诺的 onFulfilled onRejected 处理程序的处理方式与
略有不同,而不是常规拒绝:
它们被传递给 $ exceptionHandler()(在除了被转换为拒绝之外)。



这种行为的原因是未被​​捕获的错误与常规拒绝不同,因为
它可能是由例如,编程错误。在实践中,这对于用户来说是混乱的
或者是不受欢迎的,因为本地承诺或任何其他流行的承诺库
都不会将抛出的错误与常规拒绝区分开来。
(注意:虽然此行为不符合承诺/ A +规范,但也没有规定。)



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



注意:
除非明确禁用,否则仍可能会被捕获并通过未处理的拒绝到
$ exceptionHandler(),所以由于编程错误引发错误而没有另外处理(后续
onRejected handler)不会被忽视。


有关详细信息,请参阅 AngularJS开发人员指南 - 从V1.5迁移到V1.6


I have recently updated my application from Angular 1.5 to 1.6.3 and started getting Jasmine unit test failures (with PhantomJS) around promise based code I have written:

Possibly unhandled rejection: undefined thrown

Reading around I see that the accepted solution is to chain .then() with .catch() blocks to handle the rejections gracefully.

I have done this for one of my source files that I am testing to prove this gets past the error which it does.

However, it has now uncovered a further issue where an expectation I am testing when a promise rejection is called in my code is no longer passing.

This is the function I am trying to test (after adding the required catch blocks)

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

And here is the test:

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

I didnt have the .catch(angular.noop) parts in prior to upgrading to 1.6.3 and came across some posts suggesting to do this in order to make the tests happy, which certainly helped for me in getting past the unhandled rejection error in my test run.

The problem I am now facing is that for the reject test spec, there should be no call made to a remove function in my service, and so the number of calls should be zero, but it keeps coming out as 1. I added the line to reset the calls in my test to be sure it wasnt the previous test contributing (I know calls are meant to be reset between tests).

This test was running just fine when I was on 1.5, so this has to be something with the way my code\test is written not playing nicely with changes in 1.6.x

Can someone shed some light on what may be going on here please?

Thanks

解决方案

I didnt have the .catch(angular.noop) parts in prior to upgrading to 1.6.3 and came across some posts suggesting to do this in order to make the tests happy, which certainly helped for me in getting past the unhandled rejection error in my test run.

Adding .catch(angular.noop) will certainly handle the unhandled rejection.

It converts the rejected promise to a fulfilled promise!!

Your test is correctly failing because you broke your code.

For more information, see Catch method not working with $http get request


Changes to $q for AngularJS V1.6

report promises with non rejection callback

Rejected promises that do not have a callback to handle the rejection report this to $exceptionHandler so they can be logged to the console.

BREAKING CHANGE

Unhandled rejected promises will be logged to $exceptionHandler.

Tests that depend on specific order or number of messages in $exceptionHandler will need to handle rejected promises report.

treat thrown errors as regular rejections

Previously, errors thrown in a promise's onFulfilled or onRejected handlers were treated in a slightly different manner than regular rejections: They were passed to the $exceptionHandler() (in addition to being converted to rejections).

The reasoning for this behavior was that an uncaught error is different than a regular rejection, as it can be caused by a programming error, for example. In practice, this turned out to be confusing or undesirable for users, since neither native promises nor any other popular promise library distinguishes thrown errors from regular rejections. (Note: While this behavior does not go against the Promises/A+ spec, it is not prescribed either.)

This commit removes the distinction, by skipping the call to $exceptionHandler(), thus treating thrown errors as regular rejections.

Note: Unless explicitly turned off, possibly unhandled rejections will still be caught and passed to the $exceptionHandler(), so errors thrown due to programming errors and not otherwise handled (with a subsequent onRejected handler) will not go unnoticed.

For more information, see AngularJS Developer Guide - Migrating from V1.5 to V1.6

这篇关于迁移到Angular 1.6.3后无法测试被拒绝的承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆