describe("Q Service Test",() => { var q: ng.IQService; var rootScope: ng.IRootScopeService; beforeEach(inject(($q,$rootScope) => { q = $q; rootScope = $rootScope; })); it("Caught exceptions are handled properly",() => { var state = 'ok'; q.when(1) .then(() => { throw new Error("test exception"); }) .catch(() => { state = 'error'; }); rootScope.$digest(); expect(state).toBe('error'); }); });
但测试失败:
我的测试环境/工具有一些奇怪的行为,还是我错误地使用承诺机制?
$q
文件所述:
When comparing deferreds/promises to the familiar behavior of
try/catch/throw,think of reject as the throw keyword in JavaScript.
This also means that if you “catch” an error via a promise error
callback and you want to forward the error to the promise derived from
the current promise,you have to “rethrow” the error by returning a
rejection constructed via reject.
它们是类似但不是等效的,为了捕获用户定义的throw语句,你应该使用catch语句块.虽然$q的承诺应该只能抵挡被拒绝的承诺.因此,在您的情况下,返回拒绝的承诺是处理该过程的正确方式,而不是抛出用户定义的异常.
JAVASCRIPT
describe('Q Service Test',function() { var $q,$rootScope; beforeEach(inject(function(_$q_,_$rootScope_) { $q = _$q_; $rootScope = _$rootScope_; })); it('Rejected promises are handled properly',function() { var state = 'ok'; $q.when(1) .then(function() { return $q.reject('rejected'); }) .catch(function() { state = 'error'; }); $rootScope.$digest(); expect(state).toBe('error'); }); });
更新:
您的代码在浏览器中以此方式行为的原因是因为Angular的$q实现在处理promise队列时使用try / catch语句块.当任何回调引发任何错误时,它会捕获错误本身,拒绝该异常作为拒绝的原因,之后使用$exceptionHandler来记录错误.我建议你简单地拒绝承诺.
由于单元测试的原因是因为$exceptionHandler
的角度模拟实现与实际应用的$exceptionHandler
不同.前者创建了具有不同模式的提供商,默认的角模式实现使用重启模式,其中转动抛出异常而不是记录它.如果要让单元测试的行为与默认应用程序的$exceptionHandler的方式相同,那么您可以将模式设置为“log”.
JAVASCRIPT
describe('Q Service Test',$rootScope; beforeEach(module('ng',function($exceptionHandlerProvider) { $exceptionHandlerProvider.mode('log'); })); beforeEach(inject(function(_$q_,_$rootScope_) { $q = _$q_; $rootScope = _$rootScope_; })); it('Caught exceptions are handled properly',function() { var state = 'ok'; $q.when(1) .then(function() { throw new Error(); }) .catch(function() { state = 'error'; }); $rootScope.$digest(); expect(state).toBe('error'); }); });