Testing Teardown

Learn about the different methods of tearing down our Jest tests.

What does teardown entail?

Teardown is where we clean up. We don't want any configurations or mocks unknowingly making their way into our next test. This type of spillover can lead to confusing results and bugs that are difficult to track down. We perform teardown in order to wipe the slate clean at different points in our test execution and leave behind a fresh canvas with which to start anew with our next tests.

Global teardown

Our Jest configuration file allows us to add a globalTeardown field, which accepts a string value. The string value represents a path pointing to a file containing our global teardown code. This file exports a single function that we want to call at the end of running all of our test suites. The function has access to two arguments, globalConfig and projectConfig, and contains anything we need to do at the end of our test run. These steps are a sort of counterpart to something that we did during setup, for instance, stopping a process that we started in setup.

Setup files after env

Setup files after env can play a role in our teardown process. The setupFilesAfterEnv field is also available in our Jest configuration. However, it accepts an array of paths pointing to files containing this setup and teardown logic. These files are executed before our tests run but after Jest is installed in our environment, so we have access to the setup and teardown hooks that Jest makes available to us. Because of this, we can leverage our teardown hooks to add teardown logic that applies to all of our tests.

Teardown hooks

The two teardown hooks mentioned above that Jest provides us are afterEach and afterAll. Both these hooks are scoped based on where we place them. If placed in setupFilesAfterEnv, the scope is our entire test environment. If placed at the top of an individual test file, the test file is the scope, and if placed inside a describe block, the block of tests is the scope. Given this, afterEach executes after every test in its scope, before running the next test. The afterAll hook runs after all tests in scope. For example, if placed inside a describe block, the hook executes after the last test in the block completes execution before moving on to the next describe block.

Examples

In the examples below, we have a request to fetch a user from an API using Axios. Our Jest configuration file points to our global teardown inside of exampleGlobalTeardown.js, as well as our code to run once Jest is installed inside exampleSetupFileAfterEnv.js. Our fetchUser function first checks to make sure that an ID was passed in as an argument and then makes the API call. It throws an error if the call was unsuccessful and returns the user if it was successful.

In the first test in our file, we are testing that a missing ID is caught and an error is thrown, so we don’t need to mock any rejected status for Axios. In our second test, we are intending to test that an error is thrown when the request is rejected, but we have forgotten to pass in an ID. In this situation, the error is caught prior to the call being made and before the mock executes. Next, we test this same thing but this time, we test that the error thrown reflects our mock for this test. Therefore, it should throw an error with the message, “Error two.” Last, we test a successful call.

If we run these tests, we see that all our tests pass even though we know that one of our mocks didn’t get used and risks being rolled over into the next test. This doesn’t happen, though, because inside of exampleSetupFileAfterEnv.js, we reset all our mocks after each test. To see what would happen otherwise, comment this line out and watch our test fail.

Get hands-on with 1400+ tech skills courses.