Vi sono sicuramente utilizzando il meccanismo di promessa in modo non corretto, gettando un'istruzione throw definita dall'utente non costituisce per la cattura come una promessa di rifiuto in modo corretto. Come indicato nella documentazione $q
:
Quando si confrontano deferreds/promesse al comportamento familiare di try/catch/tiro, pensa di rifiutano come tiro parola chiave in JavaScript. Questo significa anche che se si "cattura" un errore tramite un call di errore promessa e si desidera inoltrare l'errore alla promessa derivata da l'attuale promessa, è necessario "ripianificare" l'errore restituendo un rifiuto creato tramite rifiutare.
Sono simili ma non equivalenti, per catturare istruzioni di lancio definite dall'utente, è necessario utilizzare i blocchi di istruzioni catch
. Mentre le promesse $q
dovrebbero solo promesse rifiutate catch
. Quindi, nel tuo caso, restituendo una promessa respinta è il modo corretto di gestire il processo invece di lanciare un'eccezione definita dall'utente.
DEMO
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');
});
});
UPDATE:
Il motivo per cui il codice si comporta in questo modo nel browser, è perché $q
implementazione di angolare utilizza l'istruzione try/catch
blocchi nell'elaborazione della coda di promessa. Quando uno qualsiasi dei richiami genera errori, rileva l'errore stesso, lo rifiuta con l'eccezione come motivo di rifiuto, successivamente utilizza $exceptionHandler
per registrare l'errore. Ti consiglio di restituire semplicemente la promessa respinta.
quanto riguarda il motivo per cui i test di unità agiscono in questo modo è dovuto angular-mocks
attuazione del $exceptionHandler
è differente con dell'applicazione effettiva $exceptionHandler
. Il primo crea un provider con diverse modalità, l'implementazione predefinita di angock-mocks utilizza la modalità rethrow
che a sua volta lancia l'eccezione invece di registrarla. Se si desidera che i test unitari si comportino allo stesso modo di come l'applicazione predefinita è $exceptionHandler
, è possibile impostare la modalità su 'log'
.
DEMO
JAVASCRIPT
describe('Q Service Test', function() {
var $q,
$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');
});
});
Grazie per la tua risposta dettagliata. Rimane una domanda: come mai la mia versione con 'throw' fallisce il test e funziona come previsto nel browser, con l'eccezione che viene consegnata nel blocco' .catch'? – Impworks
Hai detto che funziona ** come previsto nel browser **, quindi puoi mostrare il codice per quella parte? – ryeballar
ovviamente: https://jsfiddle.net/eqf54zzm/ – Impworks