Table of contents
1.
Introduction
2.
Repeating Setup
2.1.
Program
2.1.1.
Program
3.
One-Time Setup
3.1.
Program
4.
Scoping
4.1.
Program
4.2.
Program
4.3.
Output
5.
FAQs
6.
Key Takeaways
Last Updated: Mar 27, 2024

Setup and Scoping in Jest

Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

While we write tests using the jest framework, we often need some setup and finishing work after running tests. The jest framework provides helper functions to take care of this.

There are multiple ways of performing setup for a test. Different kinds of tests can use other setup methods. In this blog, explore various setup and teardown methods in jest using examples and learn about the scope of tests in jest.

Before diving into the article you can check out the Getting started with Jest and Writing Your First Unit Test with Jest article on coding ninjas to understand jest basics better.

Repeating Setup

When we have to do a particular work repeatedly for many tests, we can use beforeEach and afterEach.

beforeEach and afterEach are part of Globals. These methods and objects are put into the global environment by jest, and you don't have to require or import something to use them. We use Many such Globals for setup and teardown in tests performed using jest.

  • beforeEach: Runs a function before each test when a file runs. If a function returns a promise or is a generator, Jest waits for the promise to resolve before running the test. 
  • afterEach: Runs a function after each test when a file completes. If a function returns a promise or is a generator, Jest waits for that promise to resolve before continuing.

For example, let's assume that several tests in our test case interact with a database of Indian cities. You have a method initializeDatabase() that requires calling before each test and a clearDatabase() that requires calling after each test. Then you can use:

Program

beforeEach(() => {
  initializeDatabase();
});
afterEach(() => {
  clearDatabase();
});
test("city database has New Delhi", () => {
  expect(isCity("New Delhi")).toBeTruthy();
});
test("city database has Mumbai", () => {
  expect(isCity("Mumbai")).toBeTruthy();
});
You can also try this code with Online Javascript Compiler
Run Code

beforeEach and afterEach can handle asynchronous code in the same manner that tests can run asynchronous code, i.e., they can either take a done parameter or return a promise. For example, if initializeDatabase() is returning a promise that's resolved when initializing the database, we would then return the promise like:

Program

beforeEach(() => {
  return initializeDatabase();
});
You can also try this code with Online Javascript Compiler
Run Code

One-Time Setup

In some situations, you need to perform the setup only once for all the tests at the beginning of a file. One-time setup can be especially troublesome when it is asynchronous, so it can't be done inline. The jest framework provides beforeAll and afterAll to handle this case.

  • beforeAll: Runs a function before any of the tests in the file that runs. If the function returns a promise or is a generator, Jest waits for that promise to resolve before running tests. 
  • Afterall: Runs a function after all the tests in this file have been completed. If the function returns a promise or is a generator, Jest will wait for that promise to resolve before continuing.

For example, if both initializeDatabase and clearDatabase returned promises, and we could reuse the city database between tests, we may change our test code from the above example like:

Program

beforeAll(() => {
  return initializeDatabase();
});
afterAll(() => {
  return clearDatabase();
});
test("city database has New Delhi", () => {
  expect(isCity("New Delhi")).toBeTruthy();
});
test("city database has Mumbai", () => {
  expect(isCity("Mumbai")).toBeTruthy();
});
You can also try this code with Online Javascript Compiler
Run Code

Scoping

In the jest framework, beforeAll and afterAll blocks apply to every test in a file by default. You can also group multiple tests using a describe block. In simpler terms, describe(name, fn) creates a block that can group various related tests.

When beforeAll and afterAll are inside a describe block, these blocks only apply to the tests within that particular describe block.

For example, let's assume we didn't just have a city database but also had a food database. We could then have a different setup for different tests like this.

Program

// Applies to all tests here.
beforeEach(() => {
  return initializeDatabase();
});
test("city database has New Delhi", () => {
  expect(isCity("New Delhi")).toBeTruthy();
});
test("city database has Mumbai", () => {
  expect(isCity("Mumbai")).toBeTruthy();
});
describe("matching cities with foods", () => {
  // Applies only to the tests inside this describe block.
  beforeEach(() => {
     return initializeFoodDatabase();
  });
  test("New Delhi <3 Momos", () => {
     expect(isValidCityFoodPair("Vienna", "Momos")).toBe(true);
  });
  test("Mumbai <3 Pav", () => {
     expect(isValidCityFoodPair("San Juan", "Vada Pav")).toBe(true);
  });
});
You can also try this code with Online Javascript Compiler
Run Code

Note that at the top-level, beforeEach block is executed before the beforeEach block that is inside the describe block. An illustration of the order of execution of all hooks may be helpful to understand.

Program

beforeAll(() => console.log("1 : beforeAll"));
afterAll(() => console.log("1 : afterAll"));
beforeEach(() => console.log("1 : beforeEach"));
afterEach(() => console.log("1 : afterEach"));
test("", () => console.log("1 : test"));
describe("Scoped or Nested block", () => {
  beforeAll(() => console.log("2 : beforeAll"));
  afterAll(() => console.log("2 : afterAll"));
  beforeEach(() => console.log("2 : beforeEach"));
  afterEach(() => console.log("2 : afterEach"));
  test("", () => console.log("2 : test"));
});
You can also try this code with Online Javascript Compiler
Run Code

Output

As seen above, Jest executes all describe handlers in a test file before running any actual tests. That is is another reason to perform setup inside before*and after* handlers rather than inside a describe block. Once completing describe blocks, Jest runs all the tests serially in the order they were encountered in the collection phase by default, waiting for each one to finish and tie up before moving on.

FAQs

  1. What is a teardown function?
    Code written in a teardown() block is run upon completion of a test file, even if an error exists. Jest executes multiple calls to teardown() in the order they were created.
     
  2. What is setUp and teardown in unit testing?
    When we define a setUp() method, the test runner runs that method prior to each test. Similarly, if we define a tearDown() method, the test runner will invoke that method after each test.
     
  3. How do you test a Promise reject on Jest?
    You can use the .resolves matcher in your expected statement, and Jest will wait for the promise to resolve. If that promise is rejected, the test will fail automatically.
     
  4. How do you mock a Promise in Jest?
    You can call jest.mock('../request'), which tells Jest to use a manual mock and expects the return value of a Promise that resolves. You can follow this article to understand mocking in Jest.

Key Takeaways

This article has gone through different approaches to set up and teardown a test file in the jest framework. In other testing situations, we call different setups as per the requirements. A proper setup and teardown structure are often essential to a test file.

We have also learned about the scope of testing in jest and understood the order of execution. When you work on more testing examples on jest, the concept of scoping and setup will become more apparent. You can start here

Hence learning never stops, and there is a lot more to learn.

So head over to our practice platform Coding Ninjas Studio to practice top problems, attempt mock tests, read interview experiences, and much more. Till then, Happy Learning!

Live masterclass