A beginner’s guide to unit testing with Jest | Part 2

Syed Safayet Karim
REWRITE TECH by diconium
8 min readNov 8, 2022

The why, what and how of unit testing

This is the second part of my series about unit testing using Jest. If you missed out on the first part where we talk about the basics of unit testing and its importance, no problem: you can check it out here.

What actually is Jest ?

Jest is a popular test framework for JavaScript created by Facebook which was primarily designed for React applications but currently is widely used with other frameworks as well. It became extremely popular among other testing libraries due to its “all batteries zero config” approach and its extensive built-in matchers which ensure that almost all scenarios can be tested. It also offers enriched documentation options making it easier for beginners to start using it. Jest provides all the essential tools for running tests, making assertions, mocking implementations, and much more other functionalities in a single package.

Some of the characteristics of Jest include:

1. Almost zero configuration required. This means that you only need to install Jest as a dependency for the project and with no or small adjustments we can start writing tests for our application.

2. Jest tests run in parallel — this in turn greatly reduces the test execution time.

3. Tests run in isolation: Isolation is a very important property when running tests. It makes sure that different tests don’t influence each other’s results as each tests runs in its own sandbox.

4. Powerful Mocking support

5. Jest provides built-in support for code coverage out of the box

6. Supports snapshot testing: Snapshot is a useful tool for front-end testing that ensures that the UI does not show any unexpected behaviour. The way it works is that it takes a snapshot of the component and then whenever the component changes it takes another snapshot and compares it with the already saved one. We will see that the snapshot fails if the component has changed. This allows us to check and validate if the change was unexpected or not and if it was an intended change, the snapshot can be updated to the latest version of the component in order for the tests to pass.

7. Rich API: Jest is known for having a rich API, offering a lot of specific built-in methods for very specific needs. Besides that, it provides extensive documentation that should help in getting up to speed with it quickly.

Photo by Chokniti Khongchum: https://www.pexels.com/de-de/foto/labor-reagenzglaser-2280549/

Now let’s move on to some hands-on experience

Installing Jest

Running individual tests without installing Jest can be done using npx jest testname command. It is however recommended to have it installed to run all the tests in parallel and to have access to its other features like code coverage.

Install the Jest package to a new or existing project’s package.json file using your package manager of choice:

That’s it, this simple command will install Jest as a project dependency! We’re now ready to run tests with Jest.

Running Jest using the CLI

For running Jest from the command line we need to configure an NPM script for running our tests. Open up package.json and configure a script named test for running Jest:

Then we can simply run the newly created script from package.json to execute our tests. For example:

Running this command will run all the tests that we have created for this project.

Bonus tip for running the tests:

You can also just simply run npm test or yarn test or even shorter npm tcommand to execute the tests which actually makes the command much shorter and is a time saver.

How to write your first unit test with Jest?

Jest files usually end with *.spec.js or *.test.js and by default, Jest expects to find test files in a folder called __tests__ in the project folder and will automatically run those files or any files that has the *.test or *.spec extensions. So its kind of a standard practice to add our test files inside a __tests__ directory.

Next, create an addNumbers.js file with an add function and test if it works as expected.

Here, we have a simple arrow function with explicit return that takes in two values and adds them.

Now let’s import the function in our test suite and check its output. To get started, create a test file, addNumbers.test.js, with the following:

* The describe block is an outer description for the test suite which means it represents a generic container for all the tests that we are going to write for the different cases of the addNumber.js file.

* Next we have the individual test block that is used to represent a single test. The name of the test is represented by the strings in quotes.

* Moving to the code in the expect block — `expect` is nothing but an assertion where we can specify the expected behaviour of the code we are testing. In this case here we are just checking that if we pass 1 and 2 to the addNumbers function it should return 3.

* Here, the `.toBe` matcher is used to define the expected output of the invoked function in the expect statement. The Jest framework has a number of defined matchers, some of them are:

> toBeNull matches only null

> toBeUndefined matches only undefined

> toBeDefined is the opposite of toBeUndefined

> toBeTruthy matches anything that an if statement treats as true

> toBeFalsy matches anything that an if statement treats as false

> toBeGreaterThan or toBeLessThan for number value comparisons

> toMatch accepts a Regex pattern to match a string output

> toBeCloseTo can be used for rounding off numbers

> toThrow can be used to check for exceptions

> toContain can be used to see if a value exists in an Array

In order to run this test, simply run the command npm test in the terminal or command prompt at the project location.

You will see the output as shown below.

We can further test if the function works by adding an incorrect assertion. For example

Then running these tests will show us that it didn’t pass and would also give us what we expected and what it received which is helpful to see where and why it broke.

Here we are expecting a sum of 1 and 2 to equal 5 which is not correct.

After executing this we will get something like this.

The nice part about the failing test is the feedback that we receive from Jest. Here we can see that we expected the function to return 5 but it actually returned 3. This helps us to debug our code and find any possible bugs. However in this case the issue was not with the function implementation but with the expected result. We can fix this test by updating the assertion to check that the addition of 1 and 2 should not equal to 5.

The following test passes as the sum of 1 and 2 does not equal 5 and this is what is expected in the assertion.

The test above does not necessarily mean that the functionality is working as expected.

Here we are only making sure that the addition of two numbers is not 5 but think of a situation where one or both of the numbers are undefined because it was not properly fetched from the API response. With this test we would not be aware of this issue. So it’s important to check all possible scenarios when testing a functionality. For this case we can simply add more assertions as shown below for testing the other use cases.

The test passes when we run it which we can see below

Jest has a lot of useful built in assertions that we can use to test our use case. They have some nice documentation of what is available and how it can be used.

Let’s try another simple test case. Create a new file and name it as checkReceivedValue.js and add the following content

The function basically returns what it receives. Let’s create a test file with the name checkReceivedValue.test.js to check some of the function behaviour.

Here we are using the Jest built in method to check if the the function receives a null parameter then it should return a falsy output. This test passes as the expected output is what Jest has received.

In cases the function receives a truthy value, let’s write some test cases for that use case.

This should fail as shown in the screenshot below since the function returns a truthy value when it receives one and does not satisfy the assertion.

We can fix this test by checking that the assertion should be truthy when the function receives truthy values.

Then running the test with npm test checkReceivedValue will show that the test passes and the expected behaviour is same as the one received by Jest.

As you have already seen, once the idea is clear what the component should be doing then testing it is very simple.

Conclusion

As we already saw, unit testing is of high significance. Knowing what to test and covering all edge cases is really important since a thoroughly tested software makes sure that the product is secure, dependable and highly performant, leading to time-saving, satisfied customers, and cost-effectiveness. This is why we should put emphasis on writing tests immediately for any code that we implement. To get more hands-on experience in writing some advanced tests using Jest, stay tuned for the final part of this series!

--

--