Testing with fakeAsync in Angular

Nasreddine Skandrani
Front-End Tricks — TheBlog
3 min readNov 19, 2020

What the official doc says about fakeAsync?

1. https://angular.io/guide/testing-utility-apis

Runs the body of a test (it) within a special fakeAsync test zone, enabling a linear control flow coding style. See discussion above.

2. https://angular.io/guide/testing-components-scenarios#component-with-async-service (Some examples present)

3. https://angular.io/api/core/testing/fakeAsync

Some examples about fakeAsync usage

  • Interval (tick) Find the online example HERE.
  • Timer (tick) Find the online example HERE.
  • DebounceTime (tick)
    Without ngModel: Find the online example HERE.
    With ngModel: Find the online example HERE.

Note: most of the expect(s) from these examples can be replaced with expectation with dom element check for proper Integration Tests but this is related to test strategies in your project which are not the topic of this article.

  • Promise (tick/flushMicrotasks)
    I don’t want to rewrite it. You can look at this article HERE that shows an example about how to test a Promise.

!!!IMPORTANT!!! fakeAsync to test subscribed observables ? (Updated: 2020–12–23)

Example: the common case of HttpClient

When you have an http call that you need to mock some developers use of from rxjs but this is not a real good idea since it provides synchronous data and it’s not what HttpClient do in the real context of execution of your application…

What you can do instead is to use what is describe in this post HERE.
You can find a live demo about two of the solutions from the previous post HERE. Note that you need to combine with fakeAsync to be able to use these solutions.

Also another option that natanel doesn’t talk about in his post is to use a Subject from rxjs and pass his observable as a mock of the HttpClient call. So you can do next when you want to mock the http call.

fakeAsync flush method not working with setInterval ?

Yes. Please read HERE or HERE to get more details.
So use tick method to test in this case.

!!!WARNING!!! when testing with fakeAsync

Calling the first fixture.detecteChanges outside of the scope of thefakeAsync make all the tests with tick fail.

See HERE by yourself the same example on top about timer modified and FAILING.

fakeAsync OR TestScheduler to test Angular code?

  1. TestScheduler will not work for case with a pure javascript callsetTimeout for example (you should never need to do this but in case).
  2. TestSchedulernow has a run method so you can use it in the tests without modifying your angular code to pass a scheduler for interval etc…
  3. Read HERE the conclusion of the article of a core member of rxjs.
by Nicholas Jamieson

4. I see some posts about working outside of Zone in angular (example) which may put the TestScheduleras a premium testing method for observables for Angular in the futur.

5. TestScheduler from rxjs has a flush method that works with timer etc… but TestScheduler from rxjs is missing the advanceTimeBy as opposed to the rxJava equivalent HERE. (this point i need to do a follow up i saw it in rxjs 4 and now it vanishes).

Conclusion

For now personally i’ll keep using fakeAsync since I can do all my tests with it when needed.

You found this post helpful! give it some 👏👏👏.
Thank you

@FrontEndTricks

--

--