手记

Jest入门:新手必读的单元测试指南

概述

Jest是一个由Facebook开发的开源测试框架,适用于各种规模的JavaScript和TypeScript项目。本文提供了Jest入门指南,介绍了Jest的主要特点、应用场景、安装方法以及如何编写第一个测试用例。通过学习本文,读者可以快速掌握Jest的基本使用方法和核心概念,开始为自己的项目编写高质量的单元测试。

Jest简介

什么是Jest

Jest是一个由Facebook开发的开源测试框架,主要用来为JavaScript和TypeScript项目编写单元测试。它提供了一套简洁且强大的功能,使得编写、运行和调试单元测试变得简单高效。Jest的显著特点是易于使用、内置测试运行器、内置模拟函数和零配置等。

Jest的主要特点

  • 零配置:大多数情况下,你不需要配置任何东西即可开始使用Jest。
  • 内置模拟函数:Jest提供了一套强大的模拟(Mocking)工具,使得测试依赖变得简单。
  • 自动收集测试文件:Jest会自动搜索项目中的测试文件,无需手动指定。
  • 内置断言库:提供了丰富的断言方法,简化了测试编写。
  • 内置测试运行器:无需额外安装测试运行器,Jest内置了高效的测试执行器。
  • 代码覆盖率报告:可以自动生成代码覆盖率报告,帮助开发者了解哪些代码已经被测试覆盖。

Jest的应用场景

Jest适用于各种规模的JavaScript/TypeScript项目,包括Web前端、Node.js后端、React组件等。它适用于任何需要编写单元测试的场景,例如:

  • 测试组件的渲染结果。
  • 测试函数的返回值。
  • 测试异步代码。
  • 测试类和对象的行为。
  • 测试代码的覆盖率。
安装Jest

本地安装Jest

Jest可以单独安装,也可以通过create-react-app等工具自动安装。这里以单独安装Jest为例,介绍如何在项目中设置Jest。

  1. 创建一个新的项目目录,例如:my-project
  2. 进入项目目录并初始化一个新的Node.js项目,安装Jest。
mkdir my-project
cd my-project
npm init -y   # 初始化一个新的Node.js项目
npm install --save-dev jest

通过npm install --save-dev jest命令,Jest被安装为项目的开发依赖。

安装Jest的方法和命令

除了npm install方法,也可以使用yarn工具安装Jest。例如:

yarn add --dev jest

安装完成后,可以在项目的package.json文件中看到jest作为devDependencies被添加。

为了使用Jest,还需要在项目中配置jest。可以在项目根目录中创建一个jest.config.js文件,或者直接在package.json文件中添加jest配置。

{
  "jest": {
    "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$"
  }
}

这个配置将测试文件的路径限定为__tests__文件夹下的所有文件,或者文件名中包含testspec的文件,并且文件扩展名为.jsx.tsx

编写第一个测试用例

创建测试文件

在项目中创建一个新的文件夹__tests__,然后在这个文件夹中添加一个文件,命名为math.spec.js,表示这是一个测试文件。文件名通常以.spec.js.test.js结尾。

mkdir __tests__
touch __tests__/math.spec.js

编写简单测试用例

math.spec.js文件中编写一个简单的测试用例,测试一个加法函数。

// __tests__/math.spec.js
const add = (a, b) => a + b;

test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

这里使用了Jest提供的test函数来定义测试用例。test函数接受两个参数,一个是测试用例的描述,另一个是包含测试逻辑的函数。expect函数用来断言测试结果,toBe函数用来检查结果是否等于期望值。

运行测试用例并查看结果

在命令行中运行jest命令来执行测试:

npx jest

输出结果将显示测试是否通过。如果测试通过,输出中将显示PASS,并且会看到如下信息:

PASS  __tests__/math.spec.js
  ✓ adds 1 + 2 to equal 3 (5ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.472s
Ran all test suites.

表示测试用例通过。

Jest的核心概念

断言

在Jest中,断言是用来检查预期结果和实际结果是否一致的工具。断言是测试的核心,Jest提供了丰富的断言方法,例如toBetoEqualtoHaveBeenCalled等。

常用断言方法

  • toBe:用于检查两个值是否相等。
  • toEqual:用于检查两个对象是否相等。
  • toHaveBeenCalled:用于检查一个函数是否被调用过。
test('equality assertions', () => {
  const value = 1;
  expect(value).toBe(1);    // 成功
  expect(value).toEqual(1); // 成功
});

test('addition', () => {
  const sum = (a, b) => a + b;
  expect(sum(1, 2)).toBe(3);
});

test('mock function', () => {
  const mockFunction = jest.fn();
  mockFunction();
  expect(mockFunction).toHaveBeenCalled();
});

期望

期望是断言的一种,用来描述预期的结果。例如,期望一个函数的返回值为某个特定值。

期望方法

  • expect(result).toBe(expected):检查结果是否等于期望值。
  • expect(result).toEqual(expected):检查结果是否深度等于期望值。
  • expect(result).toBeGreaterThan(expected):检查结果是否大于期望值。
test('check equality', () => {
  const result = 10;
  expect(result).toBe(10);
});

test('check greater than', () => {
  const result = 15;
  expect(result).toBeGreaterThan(10);
});

模拟函数

模拟(Mocking)是指在测试中模拟出一个假的行为,而不是实际执行真实的行为。Jest提供了jest.fn()来创建一个模拟函数。

模拟函数的使用

  • jest.fn():创建一个新的模拟函数。
  • mockFunction.mockImplementation(func):给模拟函数设置行为。
  • mockFunction.mockReturnValue(val):设置模拟函数的返回值。
const mockFunction = jest.fn();

test('mock implementation', () => {
  mockFunction.mockImplementation(() => 'hello');
  expect(mockFunction()).toBe('hello');
});

test('mock return value', () => {
  mockFunction.mockReturnValue('world');
  expect(mockFunction()).toBe('world');
});
测试异步代码

测试Promises

测试异步代码时,可以使用Jest的await关键字来等待Promise解析。

测试Promise示例

const fetchUserData = (id) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ id, name: 'John Doe' });
    }, 1000);
  });
};

test('fetch user data', async () => {
  const user = await fetchUserData(1);
  expect(user.id).toBe(1);
  expect(user.name).toBe('John Doe');
});

测试Async/Await

使用async/await关键字可以让异步代码看起来更像同步代码,使得代码更易读和易维护。

测试Async/Await示例

const fetchData = async (url) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ data: 'Hello, World!' });
    }, 1000);
  });
};

test('fetch data with async/await', async () => {
  const data = await fetchData('https://example.com');
  expect(data.data).toBe('Hello, World!');
});

Jest的异步测试工具

Jest还提供了一些专门用于测试异步代码的工具,例如done回调、async函数、asyncawait关键字等。

异步测试工具示例

test('fetch data with done', (done) => {
  fetchData('https://example.com').then((data) => {
    expect(data.data).toBe('Hello, World!');
    done();
  });
});

test('fetch data with async/await', async () => {
  const data = await fetchData('https://example.com');
  expect(data.data).toBe('Hello, World!');
});
测试覆盖率

什么是测试覆盖率

测试覆盖率是指测试代码占总代码的比例。覆盖率越高,意味着测试越全面,代码越健壮。Jest可以生成详细的测试覆盖率报告,帮助开发者了解哪些代码已经被测试覆盖。

如何使用Jest计算覆盖率

在命令行中运行jest --coverage命令来计算测试覆盖率。

npx jest --coverage

输出结果将包括覆盖率报告:

------------------|----------|----------|----------|----------|----------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Lines |
------------------|----------|----------|----------|----------|----------------|
All files         |    90.91 |      100 |    87.5  |    90.91 |                |
 math.spec.js     |      100 |      100 |      100 |      100 |                |
------------------|----------|----------|----------|----------|----------------|

提高测试覆盖率的方法

  1. 增加测试用例:编写更多的测试用例,覆盖更多的代码路径。
  2. 覆盖分支:确保测试用例覆盖到所有的分支。
  3. 覆盖函数:确保测试用例覆盖到所有的函数。
  4. 覆盖复杂逻辑:编写测试用例覆盖复杂的逻辑。
  5. 代码审查:进行代码审查,找到未覆盖的代码并编写测试。

提高测试覆盖率示例

test('test multiple cases', () => {
  const multiply = (a, b) => a * b;

  expect(multiply(2, 2)).toBe(4);
  expect(multiply(2, 3)).toBe(6);
  expect(multiply(2, 4)).toBe(8);
  expect(multiply(2, 5)).toBe(10);
});

通过编写更多的测试用例,可以提高测试覆盖率。

总结,Jest是一个强大且易于使用的单元测试框架,适用于各种规模的JavaScript/TypeScript项目。通过本文的学习,你已经掌握了Jest的基本使用方法和核心概念,可以开始为你的项目编写高质量的单元测试了。

0人推荐
随时随地看视频
慕课网APP