JavaScript Testing with Jest

Jest is a JavaScript testing framework that is designed to be used with little configuration. Jest can be incorporate with Babel, TypeScript, Node, React, Angular, Vue and more, and is one of the most popular and well documented testing frameworks for JavaScript. This blog is designed to be a stripped down and streamlined introduction to Jest, with a brief explanation of the benefits of unit testing and some simple Jest tests you can write to get started. You can view the finished product on GitHub here.

Why Use Unit Testing ?

Unit testing is automated testing that focuses on a single ‘unit’ of your code, such as a function or a module. This makes the tests quick to write and to run, and therefore there can be many tests. Unit tests are specific to such a small piece of your code that it makes tracing errors easy and efficient.

The terms TDD (test-driven development) and BDD (behavior-driven development) refer to approaches to writing tests for a piece of software, and often TDD results in writing unit tests. In TDD, developers write a failing test for what they want their code to achieve first, and then write some code to pass the test. For example, if you want to write a method that gets the average of an array of integers, in TDD you would first write a unit test that fails. You would then adjust the method that is supposed to achieve this until it passes the test. In order to establish more boundaries for this method, more unit tests are written to fail, and then the method adjusted to pass them. This means that writing unit test is part of the process of test driven development.

Additionally, unit testing prevents code from becoming too fragile. Unit tests that verify a module’s functionality should still be applicable when that module has additions or changes. If a new method is added to a class and breaks existing functionality in the class, the existing unit tests will fail. This will indicate to the developer that either the new method has negative side effects, or that the scope of the change is larger than just that method and the existing unit tests need to change. Either way, the developer knows before deployment that their addition or modification breaks existing expected functionality.

Unit testing also provides a sort of make shift documentation for developers. By reading the unit tests for existing modules, a developer can establish what the functionality currently is and should be before making changes or tracking down a bug. This can help establish whether a bug is actually a bug or just missing functionality, and determine the complexity of potential updates to functionality.

Installation

To get started, run two commands in the main folder of your JavaScript folder to install Jest. I will be using npm or node package manager, but you can use yarn instead.

First run :

npm init

to initialize a new npm package and create a package.json file. You can learn more about npm init by reading the documentation, but for the sake of this blog just know that it will create a package.json file where we will store dependencies.

Next run:

npm install --save-dev jest

Note the flag:

--save-dev

This updates the devDependencies in your package, which are used only for local testing and development.

A Very Basic Test

To create our first basic test, we can follow the below steps. These steps mimic the basic documentation from the Jest getting-started page with some slight differences.

  1. Create a file named product.js and add the below code

2. Create a file named product.test.js with the below code

3. In the package.json file, change the value for “scripts” > “test” from:

"test": "echo \"Error: no test specified\" && exit 1"

to:

"test": "jest"

Your package.json file will look like this:

4. Open your terminal and run:

npm run test

If the code matches, you should expect to see a success message that looks like this:

Notice the PASS indication and the description of the test below that in gray letters

If you were to purposely make the test fail, by let’s say switching the multiplication sign for an addition sign in the product function in the product.js file, you would see this message:

If multiple tests fail, Jest will show multiple failures and where they occured

Jest is specific here, and tells us exactly what the output should have been with Expected: 12, and what the output actually was, Received: 7. This explanation of the test’s failure can help us debug what went wrong and how to fix it.

Testing Classes

In the event we want to test a JavaScript class and not just a file with exported functions, we can export the entire class as a module like so:

example.js

and import and use the Example module in a test file like so:

example.test.js

Jest Matchers

To dive deeper into the above test, the function .toBe() is what is called a ‘matcher’ in Jest. This tests value for exact equality, hence our test that matches 30 divided by 5 to equal 6 exactly. The expect() function returns an ‘expectation’ object which we then call the .toBe() matcher on.

Here is a list of some common matchers in Jest and what they test:

  • toEqual() => recursively check every field of an object or array
  • toBeNull() => matches null only
  • toBeTruthy() => match anything treated as true in an if statement
  • toBeFalsy() => match anything treated as false in an if statement
  • toBeCloseTo() => to test floating point equality
  • toBeGreaterThan() => expectation is greater than
  • toBeLessThanOrEqual To() => expectation is less than or equal to
  • toMatch() => match strings against a regular expressions
  • toContain() => check if array or iterable contains particular item
  • toThrow() => check if function throws specific error

Asynchronous Tests

One way JavaScript handles asynchronous code is promises, which Jest can also test. The test will return a promise, Jest will wait for it to resolve or reject, and the test will pass or fail accordingly. We can create two asynchronous functions in our Examples class, one that returns a resolved promise with a value, and one that returns a rejected promise with a reason:

Asynchronous functions are declared with the async keyword

Then in our example.test.js file we can write two new tests that test the returns of these asynchronous functions:

Note there are two options for running asynchronous tests above, by commenting out the previous ones you can test the later that use resolves() and rejects()

In the above example, expect.assertions(1) verifies that a certain number of assertions are called, otherwise the test would not fail.

Conclusion

This has been a basic introduction to writing Jest tests quickly and easily. However, Jest is an extensive framework with a lot of varied functionality for different use cases. You can view the Jest API documentation here or work through the Getting Started module on the Jest website, some of which I have covered here. I highly recommend implementing Jest unit testing into your next JavaScript project, and utilizing their documentation to answer questions and dive deeper into what Jest can do.

Resources:

--

--

--

I ‘m a Web Developer and a Flatiron coding bootcamp alumni. I currently work in the financial tech industry as a Front End Engineer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

React JS — Sitecore JSS AMPfied

“Sort()” of confused

Best of Codepen #1/2021

How to Use JavaScript ES6 Destructuring?

Draw A Polygon On Google Maps

Let’s Start with TypeScript

Leetcode Q144. Binary Tree Preorder Traversal

Structured content first: Why you should consider writing JSON, even if your prototype is…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Aidan McBride

Aidan McBride

I ‘m a Web Developer and a Flatiron coding bootcamp alumni. I currently work in the financial tech industry as a Front End Engineer

More from Medium

Dynamic Typing and coercion in Javascript

JAVASCRIPT PIPE AND COMPOSE

JavaScript Class Field Declarations

Advanced JavaScript Memoization with Lodash.memoize