J'ai un test d'unité de composant qui ne gère pas un rejet de promesse d'un faux comme je le souhaitais.Angular - Composant de test - Erreur lors du retour de Promise.reject de mock
J'ai cette fonction sur un composant qui envoie des données à addUserToOrganisation
et gère la promesse qu'il retourne:
public onSubmit() {
this.saveStatus = 'Saving';
this.user = this.prepareSaveUser();
this._userService.addUserToOrganisation(this.user)
.then(() => this._router.navigate(['/profile']))
.catch(error => this.reportError(error));
}
Lors du test de cette composante, j'ai fourni une maquette pour UserService
qui espionne la addUserToOrganisation
point final et renvoie une promesse quelconque:
mockUserService = jasmine.createSpyObj('mockUserService', ['getOrgId', 'addUserToOrganisation']);
mockUserService.getOrgId.and.returnValue(Promise.resolve('an id'));
mockUserService.addUserToOrganisation.and.returnValue(Promise.resolve());
Cela fonctionne très bien pour les chemins heureux (de résoudre) - je peux vérifier que this._router.navigate()
est appelé et ainsi de suite . Voici le test de réussite pour ce chemin heureux:
it('should navigate to /profile if save is successful', fakeAsync(() => {
fixture.detectChanges();
tick();
fixture.detectChanges();
component.userForm.controls['firstName'].setValue('John');
component.userForm.controls['lastName'].setValue('Doe');
component.userForm.controls['email'].setValue('[email protected]');
component.onSubmit();
tick();
fixture.detectChanges();
expect(mockRouter.navigate).toHaveBeenCalledWith(['/profile']);
}));
Cependant, j'ai des difficultés à tester le chemin «triste». Je changerai ma maquette pour retourner un Promise.reject
et, bien que j'ai un .catch
dans onSubmit
, je reçois cette erreur:
Error: Uncaught (in promise): no
C'est donc source de confusion. Voici mon test pour ce triste chemin. Notez que je change la réponse de l'appel simulé.
it('should show Failed save status if the save function fails', fakeAsync(() => {
mockUserService.addUserToOrganisation.and.returnValue(Promise.reject('no'));
fixture.detectChanges();
tick();
fixture.detectChanges();
component.userForm.controls['firstName'].setValue('John');
component.userForm.controls['lastName'].setValue('Doe');
component.userForm.controls['email'].setValue('[email protected]');
component.onSubmit();
tick();
fixture.detectChanges();
expect(component.saveStatus).toEqual('Failed! no');
}));
Quelqu'un a-t-il des idées?
J'ai essayé de supprimer le 'tick()' et j'ai toujours eu une erreur. Je ne comprends pas très bien comment cela serait inutile? Cependant, changer ma réponse fictive de 'returnValue ...' à 'callFake ...' a fait l'affaire. Je ne pense pas que je comprends à 100% la nuance ici cependant. – dafyddPrys
'callFake' crée une promesse rejetée au moment où il est appelé, donc il est chaîné avec' .catch' lors de l'appel 'component.onSubmit()' et aboutit à la promesse gérée.'returnValue' accepte la promesse rejetée existante qui devrait être enchaînée avec' .catch' immédiatement, mais ce n'est pas le cas - parce que timer est déplacé vers tick suivant avec 'tick()' avant qu'un rejet ne soit intercepté dans 'component.onSubmit()'. L'exemple avec 'setTimeout' montre exactement ce qui se passe là-bas. Cela devrait fonctionner sans 'tick()'. Je ne peux pas dire pourquoi vous obtenez toujours cette erreur sans cela. – estus