Optimizing Angular Unit Test Performance

1- Look for Circular Dependencies

I count this as number one that can create the worst performance time when running angular unit test. In fact when I fixed the circular dependencies between my libs, the test time dropped from 50 minutes to about 20 minutes. This was only by fixing the circular dependencies. The rest of time saving was based on the other actions listed below. It is somewhere between jest or angular that spend time to test dependencies and dependencies of dependencies which go endless. In perfect world, it should really thrown an error with “maximum call stack size exceeded”, but it did not. It continued the circular testing until it stopped at some point and successfully finished the test. This was exhausting the memory and cpu of the build machine that leaded to the very long time of testing. Fixing circular dependency included merging some libraries together and create some other shared API libraries to avoid the circular dependency issue.

2- Mock Components and Services, Directives, etc.

Every Angular ts file in your project should have it’s own standalone spec file. This said that you should not add any component, service, etc to your TestBed unless it’s the one that the spec file is testing. This helps you to separate the concerns and only focus on the tests you need to do. It also makes your test runs faster, because it will only executes smaller ts code per spec file, rather than importing other files and needing to execute all of them. I have even noticed failing tests reported in file a.spec, where I was only testing b.spec. This was because b.spec was importing something from a.ts file. Jest decided to test a.spec and b.spec. This just means that a.ts file was actually tested twice. Now think how in many files a.ts is being imported and how many times it’s test will run. The other way around is to add the `NO_ERRORS_SCHEMA` which I am not a fan of. If you want to learn about mocking, there is tons of examples available on the web for mocking.

3- Do not Test Modules

While I have not really implemented this yet, but I expect my test time to drop to a minute or a little over if I removed spec files for modules. If you tested a module, angular will rebuild all components inside the module, services and even other modules imported on it. If you think about it, you are testing each component, service and shared module again and again. It will just kill your test performance. I do not personally see a value of testing the module since everything inside it was already tested through their own spec files. Think about testing your app.module for example that is importing every module in the project that will end up testing every single component, service, directive, etc… again. There could be a reason to test the module file. For example if you have some factory functions in the file, then you need to test them. You can still export these functions and test them, but do not build a TestBed and add the module to it. Another solution, is to move the factory functions to it’s own file and test it.

4- Do not Import Modules Inside TestBed

This should have been covered in #2 which encourage us to mock dependent services and component, and also in #3 for not importing modules. I just have to mention this again that you should avoid also importing the modules inside your spec file. No matter it’s the module that the component your testing own, or a shared module. As much as you can avoid importing the modules, it will help a lot in tuning the performance of your test. I have even reached a point to mock some Material components to avoid importing some Material modules. This can be time consuming, but it will help you. You probably do not have to go that level and mock every material component, but evaluate each case and think about the size of the module you are importing in your test.

Summary

While working on a mono repo angular project, your number of shared libraries can grow so much that you may find yourself in a place that running a unit test becomes so painful and takes so long to finish. This can really become an obstacle of a you and your team while you are trying to work more efficiently and trying to finish your work. If you found yourself in this position, you probably have done something similar to the above that lead to this situation.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store