Create Custom Jest Matchers to Test Like a Pro

jest custom matchers

Jest is an industry-standard testing framework for JS projects. It was developed by Facebook to test their code and was made open-source. In this article, I will teach you to create custom Jest matchers to supercharge your testing skills.

What is a matcher?

A matcher (or an assertion) is a function that is used to check for a specific condition. Most often, it compares two values. Here are some of the basic matches available in Jest:

Why do we need custom matchers?

While Jest is very powerful out-of-box, there is always something specific to the project you can add. It should improve readability and reduce the amount of code by creating a custom Jest matcher for a common use case.

In one of my projects, I had to test whether a certain value was a correctly formated ISO date. It can be done with a regular expression, but I had to test it so many times, it was worth moving this logic to a custom Jest matcher.

Add a setup file

Before we add the matcher itself, it is important to add a setup file for Jest. A setup file is a file that is used to set up the environment and do things like add custom matchers, enable mocks and configure jest. Create a file called setupJest.js in the project root, this will be our set up file. Now you need to add this line to your Jest config (in package.json or jest.config.js):

"setupFilesAfterEnv": ["./setupJest.js"]

Note for React Native/Expo users: if you are using the jest-expo preset, this would not work. The problem is that the preset overwrites the setupFilesAfterEnv setting. To circumvent it, write your config like this:

Now, you overwrite the preset setupFilesAfterEnv setting and add your own file.

Write a custom Jest matcher

In this example, I am going to write a matcher that will check if a string is a correctly formatted ISO date. This is done using the expect.extend function. It accepts an object whose keys are matcher names, and values are functions that perform the actual matching. Here is the code that goes to setupJest.js

You can see that toBeISODate is a function that accepts a single value, received. You can accept more arguments, these will be passed to the matcher directly (more on that later). On lines 4-6 we check received against the regexp and on lines 14-15 we check if JS can correctly parse received.

The matcher has to return an object with two properties: pass and message. pass is easy: true if the checks pass and false if not. message is a little more confusing. When pass=false, message is the error that will be shown if expect(something).toBeISODate() fails. When pass=true, message is the error that will be shown if expect(something).not.toBeISODate() fails. It is never shown if the test passes. Now you can use this matcher like this:

const timestamp = get_timestamp_from_somewhere_unreliable();
expect(timestamp).toBeISODate();

Accept more arguments

The toBeISODate() matcher does not accept any additional arguments and it does not need to. But, suppose we want to write a matcher that checks if a number is a power of some other number. Here is the code for such a matcher, toBePowerOf():

It accepts one more argument, power. You can use this matcher in your code like this:

expect(8).toBePowerOf(2); // passes
expect(10).toBePowerOf(3); //fails
expect('abacaba').toBePowerOf(); // throws

Thank you for reading this article, I hope you found it helpful. Check out my other articles on JavaScript:

Get new content delivered to your mailbox:

leave a comment