TypeScript — Error Handling with Asynchronous Function in Chai

Aniruddha Chatterjee
SRMKZILLA
Published in
5 min readJul 6, 2020

For some reason, when I started with Mocha/Chai for my unit tests, I felt it pretty difficult to catch errors of asynchronous functions. And it caused me a lot of troubles. I knew the function will throw an error. I want the function to throw an error. But I could not properly configure my tests to handle that error gracefully. Until I figured out a way to do so!

Disclaimer: This method is inspired by Kord’s answer at https://stackoverflow.com/questions/45466040/verify-that-an-exception-is-thrown-using-mocha-chai-and-async-await but fully uses TypeScript

Prerequisites

This post is written assuming you know how to use the basics of TypeScript. Small explanations as to what our code does are given, but no elaboration is made.

Also, it will be helpful if you have Node.js and TypeScript already installed. You can try the online TypeScript Playground. But executing TypeScript with Node.js is preferred.

Since we will be using Mocha/Chai for this demo, it is assumed you already know the basics of it. If not, this post from GeekForGeeks is a great place to start.

You can refer to a previous story First Step towards TypeScript to learn how you can get started with TypeScript.

Creating an Asynchronous Function to throw an error

To begin with, we will create our simple asynchronous function to throw an error under certain cases.

Let us go through the codes.

Step 1: We create a function checkNumber() which will accept a number and check if it is positive. If true, it will return a string value.

Step 2: If the if condition is not matched, an error is thrown with a message.

That’s it. Our function is ready. And now we will be testing it using Mocha/Chai.

Creating simple unit tests

Let us install Mocha and Chai first. I will use yarn here as it is my favourite package manager. Feel free to use npm if you like.

We need to install packages as well as their type declarations. I will combine two commands using && for simplicity.

yarn add chai mocha && yarn add @types/chai @types/mocha --dev

And we are ready to write our test. We create a directory named “test” and create a file “simple.test.ts” inside the directory. So our file structure stands as

Our expected file structure

We shall now write our tests.

As stated in the prerequisites, we will not be covering how exactly Mocha/Chai works. So let us dive into the individual parts of the code.

Step 1: We created an asynchronous function expectThrowsAsync(). The sole purpose of the function is to catch an error and check if the error matches the criteria defined.

This function takes in a function reference, an array of parameters (if any) and the message to match that of the error as it’s own parameters.

Since we are passing a reference of a function as ‘method’ we cannot pass the parameters right there. So we define our parameters as an array of type any. And in the function definition, we call ‘method(…params)’. Here, we make use of the spread operator (…) to get the members of the array instead of the array. There is a link to spread operator in the ‘Further Ahead’ Section if you want to know more about it.

Step 2: We define our tests. In this example, we have defined 4 test cases.

Case 1 where we are just calling the checkNumber() function with a positive value and expect it to quietly work as intended without any error thrown.

Case 2 where we check a negative number without checking for the message. Any error thrown in this case will be allowed and our test case will pass.

Case 3 where we check a negative number with the proper message. The error thrown must match the parameter given for the test case to pass.

Case 4 where we check a negative number with the wrong message. The error thrown will not match the parameter given and this will cause the test case to fail.

Compiling and Executing our code

Now, the only thing between us and successful execution is the compilation. We will things in a different way than we have been doing earlier. We will create a TypeScript configuration file for this particular project. To do so, the command is

tsc --init

This will create a ‘tsconfig.json’ file in our project. It has lots of options which gives directives to the TypeScript compiler on how to compile our project. We shall use this file to mention our compiler that we need the ‘ES2015’ library while compilation because it has the ‘Promise’ constructor that we are using for async/await approach.

To do so, we will open the file, and search for “lib” option. To enable it, uncomment it and set the value as

lib: [“ES2015”]

Our tsconfig.json file now looks like.

The library has been included in Line 9

We are now ready to compile. The command for the same is

tsc

This will compile all of our TypeScript files into JavaScript files that Node.js can execute. Mocha is not globally available since we installed it just for this project. So we will call it using a full relative path.

./node_modules/mocha/bin/mocha

We get 3 passing test cases and 1 failing test case, just as we expected.

Expected output

Conclusion

So we learnt how we can check for errors thrown by asynchronous functions in TypeScript. Asynchronous functions need to resolve first before we can check the error.

This is not the only possible way to get the job done. However, it is a simple and effective way to do so. We can also use a callback approach. I might cover that approach in one of the upcoming posts. Till then, say tuned, stay safe. Peace out.

Further Ahead

Feel free to go through the resources and explore stuff by yourself.

--

--

Aniruddha Chatterjee
SRMKZILLA

Nocturnal animal that thrives on caffeine and loves software development.