unit test : CombineLatest - test succeedes after adding SetTimeOut

109 Views Asked by At

I'm trying to test this method:

myMethod() {
      result$ = combineLatest([observableOne$,observableTwo$]);
       result$.subscribe(([one, two]) => {
            this.result = one || two;
        });
    }
ngAfterViewInit() {
        this.myMethod();
    }

But every time the test fails:

  it('should test my method', (): void => {
            cmp.result$ = of([true, false]);
            cmp.ngAfterViewInit();
                expect(cmp.result).toBe(true);
        });

The moment i add a setTimeOut everyhing works as expected

  it('should test my method', (): void => {
            cmp.result$ = of([true, false]);
            cmp.ngAfterViewInit();
            setTimeout(() => {
                expect(cmp.result).toBe(true);
            },1000)
        });

Are there a solution to test without using the SetTimeOut ?

2

There are 2 best solutions below

0
wael jawadi On BEST ANSWER

The problem was directly related the variable that contains the result of the combineLatest "result$" So instead of assiging the result to a variable, i just returned it directly to the method it self this solution works for me:

myMethod(observableOne$: Observable<boolean>, observableTwo$: Observable<boolean>): Observable<boolean> {
        return combineLatest([observableOne$, observableTwo$]).pipe(
            map(([one, two]) => this.result = one || two
            ));
    };
ngAfterViewInit(): void {
        const observableOne$: Observable<boolean> = of(true)
        const observableTwo$: Observable<boolean> = of(false)
        this.myMethod(observableOne$,observableTwo$).subscribe();
}
 it('should test my method', (): void => {
                        cmp.myMethod(of(true), of(false)).subscribe(result => expect(cmp.result).toEqual(true));
                    });
1
The Fabio On

The problem is the timing of the variable cmp.result assignment.

in the first version the test will read cmp.result before the result$.subscribe( yields.

The second version is a little hackie, but it works as the test runs after result$.subscribe( yields.

you could change your component logic to cater for the asynchronous event, have a map function on its body:

realResult$ = combineLatest([observableOne$,observableTwo$]).pipe(map(([one, two]) => one || two));

then your test could do this:

it('should test my method', (done): void => {
  cmp.observableOne$ = of(true);
  cmp.observableTwo$ = of(false);
  cmp.realResult$.subscribe(result => {
    expect(result).toBe(true);
    done()
  });
});