Sign up for the Testim Dev Kit beta. Sign up now

Jest Testing: A Helpful, Introductory Tutorial

Initially, Jest was created by Facebook specifically for testing React applications. It’s one of the most popular ways of testing…

By Testim,

Initially, Jest was created by Facebook specifically for testing React applications. It’s one of the most popular ways of testing React components. Since its introduction, the tool has gained a lot of popularity. This popularity has led to the use of Jest for testing both JavaScript front-end and back-end applications.

In this article, we’ll talk about the ins and outs of Jest to help you get started with testing. You’ll learn more about the vocabulary associated with Jest testing, like mocks and spies. Also, we’ll cover some of the basics of Jest testing, like using describe blocks and the keywords it and expect. Finally, we’ll take a look at snapshot testing and why it’s particularly useful for front-end testing. Let’s get started!

What Is Jest?

As mentioned in the introduction, Jest has gained a lot of popularity over recent years for both front-end and back-end testing. Many large companies—including Twitter, Instagram, Pinterest, and Airbnb—use Jest for React testing.

Jest itself is actually not a library but a framework. There’s even a CLI tool that you can use from the command line. To give an example, the CLI tool allows you to run only specific tests that match a pattern. Besides that, it hosts much more functionality, which you can find in the CLI documentation.

In summary, this means that Jest offers a test runner, assertion library, CLI tool, and great support for different mocking techniques. All of this makes it a framework and not just a library.

Let’s take a deeper look at the characteristics of Jest.

Jest Characteristics

From the JestJS.io website, we can find four main characteristics of Jest:

  • Zero config: “Jest aims to work out of the box, config free, on most JavaScript projects.” This means you can simply install Jest as a dependency for your project, and with no or minimal adjustments, you can start writing your first test.
  • Isolated: Isolation is a very important property when running tests. It ensures that different tests don’t influence each other’s results. For Jest, tests are executed in parallel, each running in their own process. This means they can’t interfere with other tests, and Jest acts as the orchestrator that collects the results from all the test processes.
  • Snapshots: Snapshots are a key feature for front-end testing because they allow you to verify the integrity of large objects. This means you don’t have to write large tests full of assertions to check if every property is present on an object and has the right type. You can simply create a snapshot and Jest will do the magic. Later, we’ll discuss in detail how snapshot testing works.
  • Rich API: Jest is known for having a rich API offering a lot of specific assertion types for very specific needs. Besides that, its great documentation should help you get started quickly.

Next, let’s dive a bit further into the Jest vocabulary.

Jest Vocabulary

Let’s take a look at two of the most commonly used Jest terms that are also used in other testing tools: mock and spy.

Mock

From the Jest documentation, we can find the following description for a Jest mock: “Mock functions make it easy to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls).”

In addition, we can use a mock to return whatever we want it to return. This is very useful to test all the paths in our logic because we can control if a function returns a correct value, wrong value, or even throws an error.

In short, a mock can be created by assigning the following snippet of code to a function or dependency:

jest.fn()

Here’s an example of a simple mock, where we just check whether a mock has been called. We mock mockFn and call it. Thereafter, we check if the mock has been called:

const mockFn = jest.fn();
mockFn();
expect(mockFn).toHaveBeenCalled();

The following example also mocks a return value for checking specific business logic. We mock the returnsTrue function and let it return false:

const returnsTrue = jest.fn(() => false);
console.log(returnsTrue()); // false;

Next up, let’s explore what a spy is.

Spy

A spy has a slightly different behavior but is still comparable with a mock. Again, from the official docs, we read, “Creates a mock function similar to jest.fn() but also tracks calls to object[methodName]. Returns a Jest mock function.”

What this means is that the function acts as it normally would—however, all calls are being tracked. This allows you to verify if a function has been called the right number of times and held the right input parameters.

Below, you’ll find an example where we want to check if the play method of a video returns the correct result but also gets called with the right parameters. We spy on the play method of the video object. Next, we call the play method and check if the spy has been called and if the returned result is correct. Pretty straightforward! In the end, we must call the mockRestore method to reset a mock to its original implementation.

const video = require('./video');

test('plays video', () => {
const spy = jest.spyOn(video, 'play');
const isPlaying = video.play();

expect(spy).toHaveBeenCalled();
expect(isPlaying).toBe(true);

spy.mockRestore();
});

OK, now that we know about the two most used technical terms, let’s explore the basic structure.

Jest Basics

Let’s take a look at some basics on writing tests with Jest.

Describe Blocks

A describe block is used for organizing test cases in logical groups of tests. For example, we want to group all the tests for a specific class. We can further nest new describe blocks in an existing describe block. To continue with the example, you can add a describe block that encapsulates all the tests for a specific function of this class.

“It” or “Test“ Tests

Furthermore, we use the test keyword to start a new test case definition. The it keyword is an alias for the test keyword. Personally, I like to use it, which allows for more natural language flow of writing tests. To give an example:

describe('Beverage()', () => {
   it('should be delicious', () => {
      expect(myBeverage.delicious).toBeTruthy();
   });
});

Matchers

Next, let’s look at the matchers Jest exposes. A matcher is used for creating assertions in combination with the expect keyword. We want to compare the output of our test with a value we expect the function to return.

Again, let’s look at a simple example where we want to check if an instance of a class is the correct class we expect. We place the test value in the expect keyword and call the exposed matcher function toBeInstanceOf(<class>) to compare the values. The test results in the following code:

it('should be instance of Car', () => {
   expect(newTruck()).toBeInstanceOf(Car);
});

The complete list of exposed matchers can be found in the Jest API reference.

Snapshot Testing for React Front Ends

At last, the Jest documentation suggests using snapshot tests to detect UI changes. As I mentioned earlier, snapshot testing can also be applied for checking larger objects, or even the JSON response for API endpoints.

Let’s take a look at an example for React where we simply want to create a snapshot for a link object. The snapshot itself will be stored with the tests and should be committed alongside code changes.

it('renders correctly', () => {
   const tree = renderer
      .create(<Link page="http://www.facebook.com">Facebook</Link>)
      .toJSON();
   expect(tree).toMatchSnapshot();
});

Following, the above code renders the following snapshot:

exports[`renders correctly 1`] = `
<a
  className="normal"
  href="http://www.facebook.com"
  onMouseEnter={[Function]}
  onMouseLeave={[Function]}
>
  Facebook
</a>
`;

If the link object changes, this test will fail in the future. If the changes to the UI elements are correct, you should update the snapshots by storing the results in the snapshot file. You can automatically update snapshots using the Jest CLI tool by adding a “-u” flag when executing the tests.

Getting Started With Jest Testing

Finally, we’ve covered all the basic elements for you to get started with Jest testing. When you’re writing your first test cases, it can feel a bit uncomfortable writing mocks. However, mocks are especially useful in unit testing because they allow you to test the business logic of your function without worrying about its dependencies.

If you want to learn more about Jest testing, I suggest reading this guide on unit testing with Jest. I also want to refer you to the Jest cheat sheet. Now go forward and begin with Jest testing!

This post was written by Michiel Mulders. Michiel is a passionate blockchain developer who loves writing technical content. Besides that, he loves learning about marketing, UX psychology, and entrepreneurship. When he’s not writing, he’s probably enjoying a Belgian beer!

Testim's latest articles, right in your inbox.

From our latest feature releases, to the way it impacts the businesses of our clients, follow the evolution of our product

Blog Subscribe