Testing with fakeAsync in Angular
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?
TestScheduler
will not work for case with a pure javascript callsetTimeout
for example (you should never need to do this but in case).TestScheduler
now has arun
method so you can use it in the tests without modifying your angular code to pass a scheduler forinterval
etc…- Read HERE the conclusion of the article of a core member of rxjs.
4. I see some posts about working outside of Zone in angular (example) which may put the TestScheduler
as 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