If you’re here, you have probably already read the Angular documentation on testing, and maybe have written a few tests for your own project. If you have not, I can only suggest you do so, because this article will require some prior knowledge of Angular testing.

So at that point, you know how many hoops you need to jump through to test even the simplest of components and directives. TestBed configuration, compiling the components, creating the one you need, getting access to the directives instances, cleaning up, … And if you are working on a real-life project, you probably have many spec files across your code base, all needing the same boilerplate. So what’s the most efficient way to centralize that boilerplate, so that your actual spec files can focus on the unit tests themselves?

This article will show you a neat solution to this problem, using two little-known features: Jasmine’s user context and Typescript’s ability to type this . We’ll round it up by relying on some “advanced” parameterized typing to make sure everything is truly reusable.

Let’s open your new toys

Jasmine’s user context

Did you know that Jasmine binds all the functions declared in it , beforeEach and afterEach to the same object when running a test? This object allows you to share information across the different phases of your test, and the object gets properly destroyed at the end of each test to avoid memory leaks.

So what does that look like? Here is a simple example:

It creates a fresh new Dog object for each of the two tests, and properly tears down the object after each one. Pretty simple, you could admittedly do the same with a local variable at the beginning of your describe. There are two main advantages to this approach over local variables: it helps fight the memory leaks that keep creeping up on large projects’ tests, and it also offers a very easy way to have your beforeEach and it in two different files, which is much harder to set up with local variables.

CAUTION: We are using a plain function() {} here, rather than the very useful () => {} arrow notation from Typescript. This is on purpose, because arrow notation would prevent us from accessing the user context Jasmine assigns to this when calling our functions.

Typing a function’s context

The previous example is fine, but all the nice tools you get from using Typescript instead of Javascript disappear when you work with an abstract this that comes from Jasmine. It is automatically typed as any , so you will not get any form of autocompletion, type checking or smart navigation in your IDE.

Thankfully, recent versions of Typescript (starting at Typescript 2.0) now allow you to type this as if it were an argument of the function:

Doing so will give you back of the advantages of Typescript’s strict typing, including compilation errors when accessing unknown properties or autocompletion in your favorite IDE: