Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular test with asyncScheduler and flush - why it fails with flush()?

There is this Angular component:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { asyncScheduler, Observable, of, queueScheduler, scheduled } from 'rxjs';

@Component({
  selector: 'test-component',
  templateUrl: './test-component.component.html'
})
export class TestComponentComponent implements OnInit {
  value: string;

  constructor() { }

  ngOnInit(): void {
    const data$ = this.fetchDataScheduler();

    data$
      .subscribe(value => {
        this.value = value;
      });
  }

  private fetchDataScheduler(): Observable<string> {
    return scheduled(of('foo'), asyncScheduler);
  }

}

and the test is failing:

it('async - test setTimeout', fakeAsync(() => {
    expect(component.value).toBeFalsy();

    fixture.detectChanges(); // ngOnInit

    expect(component.value).toBeFalsy();
    flush();

    expect(component.value).toBe('foo');  // <- fails here
  }));

failing test

flush() should flush all macrotasks, but it does not. Why? If I use tick(), then the test is passing.

passing test

(Screenshots above provided by Jest and Wallaby plugin.)

Why is not passing with flush() but is passing with tick()?

flush:

Simulates the asynchronous passage of time for the timers in the fakeAsync zone by draining the macrotask queue until it is empty. The returned value is the milliseconds of time that would have been elapsed.

Repo is here: https://stackblitz.com/github/felikf/angular-testing-examples

like image 350
Felix Avatar asked Jan 08 '20 15:01

Felix


People also ask

What does flush do in Angular testing?

flushlink. Flushes any pending microtasks and simulates the asynchronous passage of time for the timers in the fakeAsync zone by draining the macrotask queue until it is empty.

How does fakeAsync work?

FakeAsync is similar in concept, except that it kind of "catches" any asynchronous operations. Any asynchronous code that is triggered is added to an array, but it is never executed… until we tell it to be executed. Our tests can then wait until those operations have completed before we make our assertions.

What does fixture detectChanges () do?

fixture. detectChanges() tells Angular to run change-detection. Finally! Every time it is called, it updates data bindings like ng-if, and re-renders the component based on the updated data. Calling this function will cause ngOnInit to run only the first time it is called.

What is tick in Angular?

The tick() function simulates the asynchronous passage of time for the timers in the fakeAsync zone in Angular test.


1 Answers

asyncScheduler is a setInterval which is a periodic macroTask, and currently the flush() API only flush non-periodic macroTasks such as setTimeout()

For now you should use tick() to make it work.

You can read more about it here

like image 93
user1 Avatar answered Sep 21 '22 19:09

user1