How to Write Tests for Components With OnPush Change Detection in Angular
Making Angular aware of changes in component tests
The Angular framework does a lot under the hood to detect changes and update the UI accordingly. Similarly to other frameworks like React or Vue.js, Angular supports data binding to always show the latest data.
While Angular is already a fast framework, we can always improve things. One improvement idea is to reduce the amount of change detection work to keep the UI as smooth as possible. For Angular components, there are two change detection strategies available:
Defaultuses the defaultCheckAlwaysstrategy in which change detection is automatic until explicitly deactivated. If you don’t specify a strategy, then this will be used.OnPushuses theCheckOncestrategy, meaning that automatic change detection is deactivated until reactivated by setting the strategy toDefault. Change detection can still be explicitly invoked by usingChangeDetectorRef.
The OnPush change detection strategy is a good choice for dumb components that typically:
- Have few or no internal states.
- Declare
Input properties to allow their parent element to provide data. - Communicate with their parent element with the help of
Output properties.
Sadly, components that use the OnPush change detection strategy are harder to test in unit tests. The problem is that such a component will run change detection only once when calling fixture.detectChanges()for the first time. There are popular issues on GitHub (example) that highlight the severity of this problem. Let’s have a look at some ideas to solve this problem:
- You can try to write your test code in such a manner that you only need to trigger change detection once. However, this can be cumbersome and some tests need multiple change detection runs.
- You can wrap your component in another component. As long as only
Inputproperties of the component provided by the wrapper component are changed, Angular should pick up these changes. For this approach, you need to create a wrapper component just to not have to deal with the change detection issue.
These approaches can work, but they seem to involve more effort than necessary in my opinion. One advantage of open source projects is that even if there’s no officially supported way, the community will often figure out a way. Now, I want to share with you what the community figured out to attempt to solve this problem.
How to Trigger Change Detection for OnPush Components in Tests
Not satisfied with having to deal with this problem, I tried out multiple ways to trigger change detection for such components in tests. Looking for a solution, I stumbled upon a neat function that I’d like to share with you:





