How do I write unit tests in a TypeScript project? In this article, we will try to answer this question and also show you how to create a unit testing environment for projects using TypeScript.

What are unit tests?

Unit tests – Tests applied across different layers of an application that test the smallest divisible logic in an application: for example, a module, class, or method.

The essence of unit tests is to write them to each new class or method, checking if the next change in the code has led to the appearance of errors (bugs) in the already tested parts of the program.

It follows that unit tests should be fast. Such tests can be performed frequently during programming. That is, after writing a new class or method, the developer writes a package of tests for them, then runs them along with the existing tests of the rest of the program. At the output, we get the code covered with tests, which allows us to avoid bugs already at the start of development.

Setting up the environment

So now to the point. Suppose we have a certain project with the following structure:

In ./src there is a cat.module.ts module that contains a simple Cat class.

As you can see, our class contains a constructor that accepts name and color values ​​as well as a couple of methods. This class will be our test object (SUT – a system under test).

Let’s create a test folder at the root of the project, in which we will store our tests.

Next, install the required npm packages:

npm install –save-dev ts-node mocha @testdeck/mocha nyc chai @types/chai

Brief description of packages:
ts-node – a package for executing TypeScript and REPL in the node.js environment.

mocha is a popular, flexible test framework that allows you to develop tests of any level. We will use it as the basis for our tests. Together with it, we use @testdeck/mocha – the implementation of the testdeck decorator for Mocha to write our tests in an OOP style.

nyc is a modern CLI of the popular Istanbul utility that calculates current test coverage of code.

chai is a popular library for checking assertions, suitable for many testing frameworks. We will use it in tandem with Mokka. Let’s also add @types/chai so that our teas can work freely with typescript types

After installing all the necessary packages, we will create a tsconfig.json file in our test folder, in which we will add TS configs which will be called separately for our tests.

In the include line, we specify to include all files in the test folder with the extension .ts

Then we will create a file register.js in the root of the project, in which we will describe the instructions for ts-node, from where to run and transpile our tests.

Next, create a .mocharc.json file there at the root, with the following content:

And the .nyrc.json file with the config of our utility for analyzing test coverage.

After adding all the necessary configs, our project tree will look like this:

Now you need to add the startup script to package.json

We have finished with the setup, now we can write the first test.

Writing tests

Create a file in the ./test folder cat.unit.test.ts file and write the following code in it:

We have now imported our Cat class from the cat.module.ts module added the imports of the required test libraries and created the necessary variables to initialize our class.

In the before section, we set the parameters necessary for the class and created an instance of the Cat class on which the tests will be passed.

Now let’s add the first test that checks that our cat exists and has the name that we gave it.

Run the test with the npm test command and get something like this in the console:

As you can see, our coverage is not complete, lines 11-15 remained untested. These are the move and say methods of the Cat class.

We add two more tests for these methods and we end up with such a file with tests:

Run our tests again and see that the Cat class now has full test coverage.

Outcome

As a result, we have created a test infrastructure for our application and now we can cover any new module or class with tests, checking that the existing code has not broken.