Search code examples
angularunit-testingrxjskarma-jasminecombinelatest

unit test : CombineLatest - test succeedes after adding SetTimeOut


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 ?


Solution

  • 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()
      });
    });