Testing Angular components
Testing components is the most challenging yet unavoidable task when developing Angular applications. I will show you a couple of strategies and a mental model to overcome that.
The tricky part of components comes from their dual nature (presentation with a template and logic with a class). Another obstacle to easy testing is that components use to have dependencies. Again, from logic and presentation.
In this post, I will show you the main strategies to get your components covered with minimum effort.
🎒Prerequisites
- Proficient as a modern Angular developer.
- Basic knowledge of testing with Jest (read my other articles if you need to refresh something)
Decoupling from logic
In a good architect Angular solution, you should have two kinds of elements: presentational (components, directives, pipes…) and logical (services, interceptors, components…). What? You say components before as a presentational element. Right, this needs a short explanation.
Angular Components are the cornerstone of web applications as they mix and match HTML with TypeScript, i.e., presentation with logic. We should do our best to keep those beasts apart. The most used pattern to do that is to have two kinds of components: smart and dumb.
Smart components, aka containers, are meant to interact with data services and to contain other components. The dumb components, aka presenters, should receive and emit data and changes through input and output properties without dependency on any data store or service.
If you follow this so-called Container-Presenter pattern, your testing issues will be halved. Presenter components don’t have service dependencies… and containers can be easily isolated from services.
What about the presentation part of a container? Well, let us get our feet wet to explore our possibilities.
Deep tests.
When testing an angular component that contains more components (or pipes or directives…), we face some integration when we import the real child components. This strategy is called deep testing because you go deep into the dependency graph.
Using real children is easy (as you don’t forget to import them and their dependencies) and allows you to search for expected renderings. On the other hand, it may be redundant if you also test those components by themselves.
Shallow tests.
If you want to isolate your container, you must mock its contents. To do so, we must create stubs of any child component and override their implementation during the test arrangement.
Of course, this strategy only allows us certain types of assertions. However, they are usually lighter to execute and focus on the responsibility of the component in question.
🌅 Summary.
You learned how to organize your Angular code to be easy to test. The more logic to extract from components, the less problematic it will be to create a component test. The same rules for the view: the more you decompose your templates, the more control you will have over your tests.
Those are my four tips for easy testing:
- ✅ Extract logic to services
- ✅ Follow the container/presenter pattern
- ✅ Test components in isolation
- ✅ Prefer shallow over deep testing
In future articles, I will give you examples of each of these types of tests.
learn, code, enjoy, repeat