Je souhaite tester un effet qui fonctionne comme suit:
Le code de l'effet ressemble à ceci:
Expected $.length = 0 to equal 3. Expected $[0] = undefined to equal Object({ frame: 20, notification: Notification({ kind: 'N', value: undefined, error: undefined, hasValue: true }) }). Expected $[1] = undefined to equal Object({ frame: 30, notification: Notification({ kind: 'N', value: undefined, error: undefined, hasValue: true }) }). Expected $[2] = undefined to equal Object({ frame: 50, notification: Notification({ kind: 'N', value: LoadEntriesSucces({ payload: Object({ entries: [ Object({ type: 'type', userText: 'userText', ipAddress: '0.0.0.0' }) ] }), type: '[Subnet Browser API] Load Entries Succes' }), error: undefined, hasValue: true }) }).
Ce que je veux tester, c'est si un effet est distribué après 5 secondes:
it('should dispatch action after 5 seconds', () => { const entries: SubnetEntry[] = [{ type: 'type', userText: 'userText', ipAddress: '0.0.0.0' }]; const action = new SubnetBrowserApiActions.LoadEntriesSucces({entries}); const completion = new SubnetBrowserApiActions.LoadEntriesSucces({entries}); actions$ = hot('-a', { a: action }); const response = cold('-a', {a: entries}); const expected = cold('- 5s b ', { b: completion }); subnetBrowserService.getSubnetEntries = () => (response); expect(effects.continuePollingEntries$).toBeObservable(expected); });
Cependant, ce test ne fonctionne pas pour moi. Le résultat du test ressemble à ceci:
@Effect() continuePollingEntries$ = this.actions$.pipe( ofType(SubnetBrowserApiActions.SubnetBrowserApiActionTypes.LoadEntriesSucces), delay(5000), switchMap(() => { return this.subnetBrowserService.getSubnetEntries().pipe( map((entries) => { return new SubnetBrowserApiActions.LoadEntriesSucces({ entries }); }), catchError((error) => { return of(new SubnetBrowserApiActions.LoadEntriesFailure({ error })); }), ); }), );
Que dois-je faire pour que ce test fonctionne?
3 Réponses :
vous pouvez utiliser le rappel done
de jasmine
it('should dispatch action after 5 seconds', (done) => { const resMock = 'resMock'; const entries: SubnetEntry[] = [{ type: 'type', userText: 'userText', ipAddress: '0.0.0.0' }]; const action = new SubnetBrowserApiActions.LoadEntriesSucces({entries}); const completion = new SubnetBrowserApiActions.LoadEntriesSucces({entries}); actions$ = hot('-a', { a: action }); const response = cold('-a', {a: entries}); const expected = cold('- 5s b ', { b: completion }); subnetBrowserService.getSubnetEntries = () => (response); effects.continuePollingEntries$.subscribe((res)=>{ expect(res).toEqual(resMock); done() }) });
Il ne teste pas du tout si la réponse est arrivée après 5 secondes :(
vous voulez tester pour tester votre temps de retard d'effet?
Eh bien, je suppose que je veux tester si tout le flux observable est le même que je m'attends à ce qu'il soit. Dans votre exemple, il n'est jamais testé si ce flux ressemble à ce que j'attends (voir variable `` attendu '')
bien sûr, ce que je voulais dire dans cet exemple, c'est que vous allez fournir un objet simulé avec votre réponse :)
La deuxième notation ne fonctionne pas avec jasmine-marbles
, utilisez des tirets à la place:
const expected = cold('------b ', { b: completion });
le problème avec les marbeaux tel quel est que le résultat sera vide car l'effet est retardé par l'opérateur de retard. Vous devrez changer le planificateur et basculer sur delayWhen. Pour moi, cela ressemble au retard même si son retard (0), il tique toujours et cela fait un retard et une désynchronisation entre votre résultat attendu du test unitaire et votre effet, mais avec du retard Quand, cela ne se produit pas.
Vous devrez faire 3 choses
1- Dans votre beforeEach
, vous devez remplacer le planificateur interne de RxJs comme suit:
const expected = cold('------b ', { b: outcome });
2- Remplacez delay, par delay Quand comme suit:
delayWhen (_x => (true? interval (50): of (undefined)))
3- Utiliser des frames, je ne sais pas vraiment comment utiliser les secondes pour cela, j'ai donc utilisé des cadres. Chaque image dure 10 ms. Donc, par exemple, mon retard ci-dessus est de 50 ms et ma trame est -b, donc c'est les 10 ms attendus + il me fallait encore 50 ms donc cela équivaut à 5 images supplémentaires qui étaient ------ b comme suit:
import { async } from 'rxjs/internal/scheduler/async'; import { cold, hot, getTestScheduler } from 'jasmine-marbles'; beforeEach(() => {..... const testScheduler = getTestScheduler(); async.schedule = (work, delay, state) => testScheduler.schedule(work, delay, state); })
Avez-vous déjà trouvé une solution? Je suis prêt à utiliser TestScheduler, mais je ne l'ai jamais fait fonctionner. dev.to/mokkapps/ …
Non, j'ai fini par ne pas le tester du tout:
Voir ma réponse ci-dessous. Cela a fonctionné pour moi. Vous pouvez également ajouter un paramètre à votre effet pour désactiver la minuterie, de sorte que vous n'ayez pas à vous soucier de passer le délai des secondes. Dis-moi si tu as besoin d'aide.