Learn how to set up Jest with TypeScript, write unit tests, mock dependencies, and handle asynchronous tests in a TypeScript environment.
Testing is a crucial part of software development that ensures your code behaves as expected. In this section, we’ll explore how to use Jest, a popular testing framework, with TypeScript. We’ll cover setting up Jest, writing unit tests, mocking dependencies, and handling asynchronous tests. By the end of this guide, you’ll be equipped to write effective tests for your TypeScript projects.
Jest is a delightful JavaScript testing framework with a focus on simplicity. It works out of the box for most JavaScript projects, and its features include:
Jest is widely used in the JavaScript ecosystem and integrates well with TypeScript, making it an excellent choice for testing TypeScript applications.
Before we can start writing tests, we need to set up Jest in our TypeScript project. Follow these steps to get started:
Initialize a TypeScript Project
First, ensure you have a TypeScript project set up. If not, you can initialize one using the following commands:
mkdir my-typescript-project
cd my-typescript-project
npm init -y
npm install typescript --save-dev
npx tsc --init
This creates a new directory, initializes a Node.js project, installs TypeScript, and generates a tsconfig.json
file.
Install Jest and TypeScript Support
Next, install Jest along with the necessary TypeScript support packages:
npm install jest ts-jest @types/jest --save-dev
jest
: The core Jest testing framework.ts-jest
: A TypeScript preprocessor for Jest.@types/jest
: TypeScript type definitions for Jest.Configure Jest
Create a jest.config.js
file in the root of your project with the following content:
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
};
This configuration tells Jest to use ts-jest
as the preset and to look for test files with a .ts
extension.
Add a Test Script
Update the scripts
section of your package.json
to include a test script:
"scripts": {
"test": "jest"
}
Now, you can run your tests using npm test
.
Unit tests are small, isolated tests that verify the behavior of individual functions or components. Let’s write a simple unit test for a TypeScript function.
Create a Function to Test
Create a file named mathUtils.ts
with the following content:
export function add(a: number, b: number): number {
return a + b;
}
This function takes two numbers and returns their sum.
Write a Test for the Function
Create a test file named mathUtils.test.ts
in a __tests__
directory:
import { add } from '../mathUtils';
test('adds two numbers', () => {
expect(add(2, 3)).toBe(5);
});
In this test, we import the add
function and use Jest’s test
function to define a test case. The expect
function is used to assert that the result of add(2, 3)
is 5
.
Run the Test
Run the test using the following command:
npm test
You should see output indicating that the test passed.
In real-world applications, functions often depend on external modules or services. Jest provides powerful mocking capabilities to isolate the code under test.
Create a Module to Mock
Suppose we have a module api.ts
that fetches data from an API:
export async function fetchData(url: string): Promise<any> {
const response = await fetch(url);
return response.json();
}
Mock the Module in Tests
Create a test file api.test.ts
and mock the fetchData
function:
import { fetchData } from '../api';
jest.mock('../api', () => ({
fetchData: jest.fn().mockResolvedValue({ data: 'mocked data' }),
}));
test('fetches data from API', async () => {
const data = await fetchData('https://api.example.com/data');
expect(data).toEqual({ data: 'mocked data' });
});
Here, we use jest.mock
to replace the fetchData
function with a mock implementation that returns a resolved promise with mocked data.
Asynchronous code is common in modern applications, and Jest provides tools to test such code effectively.
Create an Asynchronous Function
Let’s create an asynchronous function delay.ts
:
export function delay(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
This function returns a promise that resolves after a specified delay.
Write an Asynchronous Test
Create a test file delay.test.ts
:
import { delay } from '../delay';
test('waits for the specified delay', async () => {
const start = Date.now();
await delay(100);
const end = Date.now();
expect(end - start).toBeGreaterThanOrEqual(100);
});
In this test, we use async
and await
to handle the promise returned by delay
. We check that the elapsed time is at least the specified delay.
Testing should be an integral part of the development process. Here are some tips to encourage writing tests:
Experiment with the examples provided in this guide. Here are some suggestions:
add
function to handle more complex operations and write corresponding tests.To help visualize the testing process, let’s use a Mermaid.js flowchart to illustrate the flow of a typical test case:
graph TD; A[Start] --> B[Write Function] B --> C[Write Test] C --> D[Run Test] D --> E{Test Passed?} E -->|Yes| F[Refactor Code] E -->|No| G[Fix Code] G --> C F --> H[End]
This flowchart shows the iterative process of writing a function, testing it, and refining the code based on test results.
For further reading and exploration, consider the following resources:
To reinforce your learning, try answering the following questions and challenges:
By incorporating Jest into your TypeScript projects, you can ensure your code is reliable and maintainable. Happy testing!