为了账号安全,请及时绑定邮箱和手机立即绑定

Jest课程:零基础入门到上手实践

标签:
单元测试
概述

Jest是一款由Facebook开发的开源JavaScript测试框架,广泛应用于JavaScript、TypeScript、React和Node.js等技术栈的测试中。本文将介绍Jest的安装配置、基础语法以及高级特性,并提供实战案例帮助读者更好地理解和使用Jest。

Jest课程:零基础入门到上手实践
Jest简介

什么是Jest

Jest是一款由Facebook开发的开源JavaScript测试框架,主要用于测试JavaScript、TypeScript、React和Node.js应用。Jest旨在为开发者提供一个简洁、快速的测试体验,并且能够很好地集成到现有的工作流程中。Jest能够在本地启动一个内嵌的Web服务器,提供一个易于使用的接口来运行测试,并且能够自动捕捉测试覆盖率。

Jest的主要功能和优势

Jest的主要功能和优势包括:

  • 快速的测试执行速度:Jest使用了内置的文件监视器和并行测试执行,使得测试执行速度极快。
  • 零配置的测试环境:Jest可以无缝集成到现有的项目中,具有零配置或很少配置的需求。
  • 可靠的断言库:Jest自带了一个断言库,可以方便地进行各种断言操作,支持多种断言方法,如相等、不等、包含、类型检查等。
  • 强大的模拟功能:可以轻松创建模拟对象,用于替代真实的依赖,便于进行单元测试。
  • 内置的测试覆盖率工具:Jest可以自动计算测试覆盖率,并生成详细的覆盖率报告,帮助开发者了解哪些代码已经被测试覆盖。
  • 简洁的测试语法:Jest提供了简洁的测试语法,使得编写测试代码变得简单易懂。
  • 易于集成到CI/CD环境:Jest可以很容易地集成到持续集成和持续部署环境中,如GitHub Actions、GitLab CI等。

Jest在测试中的应用

Jest广泛应用于JavaScript、TypeScript、React和Node.js等技术栈的测试中。以下是Jest的一些应用场景:

  • 单元测试:Jest可以用于编写单元测试,对单个函数或方法进行测试。
  • 集成测试:Jest也可以用于集成测试,测试多个模块之间的交互。
  • 端到端测试:Jest可以与测试工具如React Testing Library结合使用,进行端到端测试。
  • 代码覆盖率分析:Jest提供了测试覆盖率分析功能,帮助开发者了解哪些代码已经被测试覆盖。
  • 异步和定时测试:Jest可以很好地处理异步代码和定时器,使得编写异步测试变得简单。
  • 模拟依赖:Jest提供了强大的模拟功能,可以模拟外部依赖,便于编写单元测试。
Jest安装与配置

如何安装Jest

  1. 全局安装Jest
npm install --global jest
  1. 项目中安装Jest

在项目根目录下,执行以下命令:

npm install --save-dev jest
  1. 初始化Jest配置

在项目根目录下执行以下命令,初始化Jest配置文件:

npx jest --init

根据提示选择合适的配置选项,Jest会自动生成package.json中的scripts部分和.jest目录下的配置文件。

配置Jest的基本步骤

  1. 配置package.json

package.json中添加测试脚本:

{
  "scripts": {
    "test": "jest"
  }
}
  1. 配置.jest目录下的配置文件

.jest目录下,可以创建jest.config.jsjest.config.json文件来配置Jest的选项。

例如,配置文件jest.config.js

module.exports = {
  testEnvironment: 'jsdom',
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/__mocks__/fileMock.js',
    '\\.(css|less|scss)$': 'identity-obj-proxy'
  },
  transform: {
    '^.+\\.(t|j)sx?$': 'babel-jest'
  },
  testPathIgnorePatterns: ['<rootDir>/node_modules/'],
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$'
};

使用Jest进行项目集成

  1. 创建测试文件夹

在项目中创建一个专门存放测试文件的文件夹,例如__tests__

  1. 编写测试用例

__tests__文件夹中,为每个需要测试的文件创建相应的测试文件。例如,如果有一个add.js文件,则可以在__tests__文件夹中创建add.test.js文件。

  1. 运行测试

在命令行中运行以下命令:

npm run test

这将运行所有位于__tests__文件夹中的测试文件,并输出测试结果。

Jest基础语法

测试用例的编写

一个简单的测试用例通常由以下几个部分组成:

  1. 描述:一个简短的描述,用于描述整个测试用例的目的。
  2. 测试函数:测试函数通常使用ittest来定义。测试函数包含具体的测试逻辑。
  3. 断言:断言是用于验证预期结果是否正确的方法。

示例代码:

// add.test.js
import add from './add';

describe('add函数测试', () => {
  it('应能正确执行两个数的相加', () => {
    expect(add(1, 2)).toBe(3);
  });

  it('应能正确处理浮点数相加', () => {
    expect(add(1.5, 2.5)).toBe(4);
  });

  it('应能正确处理负数相加', () => {
    expect(add(-1, -2)).toBe(-3);
  });
});

断言的使用方法

Jest内置了一个丰富的断言库,提供了多种断言方法。以下是一些常见的断言方法:

  • toBe(val):用于验证两个值是否相等。
  • toEqual(val):用于深度比较两个对象或数组是否相等。
  • not.toBeNull():用于验证值不为null
  • toHaveBeenCalled():用于验证函数是否被调用过。
  • toHaveBeenCalledWith():用于验证函数是否被调用,并且传递的参数与预期相同。

示例代码:

import { add } from './add';

const mock = jest.fn();
mock.add = add;

describe('add函数测试', () => {
  it('add应被调用', () => {
    mock.add(1, 2);
    expect(mock.add).toHaveBeenCalled();
  });

  it('add应被调用,且参数正确', () => {
    mock.add(1, 2);
    expect(mock.add).toHaveBeenCalledWith(1, 2);
  });
});

使用描述和标题

Jest允许使用描述和标题来组织测试用例,使得测试代码更加清晰和易于理解。描述用于描述测试用例的总体目的,而标题则用于描述具体的测试。

示例代码:

import add from './add';

describe('add函数测试', () => {
  describe('基本功能', () => {
    it('应能正确执行两个数的相加', () => {
      expect(add(1, 2)).toBe(3);
    });

    it('应能正确处理浮点数相加', () => {
      expect(add(1.5, 2.5)).toBe(4);
    });
  });

  describe('边界情况', () => {
    it('应能正确处理负数相加', () => {
      expect(add(-1, -2)).toBe(-3);
    });

    it('应能正确处理大数相加', () => {
      expect(add(Number.MAX_SAFE_INTEGER, 1)).toBe(Number.MAX_SAFE_INTEGER + 1);
    });
  });
});
Jest高级特性

间谍函数和模拟函数

间谍函数(Spy)和模拟函数(Mock)是Jest提供的两种重要功能,用于测试函数的调用情况和返回值。

  • 间谍函数:用于监视函数的调用情况,可以获取函数的调用次数、传递的参数等信息。
  • 模拟函数:用于模拟真实的函数,可以控制函数的返回值、抛出异常等行为。

示例代码:

import add from './add';
import { mockAdd } from './mockAdd';

describe('add函数测试', () => {
  it('应能正确执行add', () => {
    const spy = jest.fn(mockAdd);
    const result = add(1, 2);
    expect(spy).toHaveBeenCalled();
    expect(spy).toHaveBeenCalledWith(1, 2);
    expect(result).toBe(3);
  });

  it('应能正确处理mockAdd抛出异常的情况', () => {
    const mock = jest.fn().mockImplementation(() => {
      throw new Error('模拟异常');
    });
    const result = add(1, 2);
    expect(mock).toHaveBeenCalled();
    expect(result).toBeUndefined();
  });
});

使用mocks进行测试

Jest提供了强大的模拟功能,可以用于模拟模块导入、文件系统操作、HTTP请求等。以下是一些常见的模拟方法:

  • jest.mock(module):用于模拟导入的模块。
  • jest.fn().mockImplementation(fn):用于定义模拟函数的行为。
  • jest.spyOn(object, method):用于监视对象的方法,获取其调用情况。

示例代码:

// mockAdd.js
export function mockAdd(a, b) {
  return a + b;
}

// add.test.js
import add from './add';
import { mockAdd } from './mockAdd';

describe('add函数测试', () => {
  it('应能正确执行mockAdd', () => {
    jest.mock('./mockAdd', () => ({
      mockAdd: jest.fn().mockImplementation((a, b) => a + b)
    }));
    const result = add(1, 2);
    expect(result).toBe(3);
  });

  it('应能正确处理mockAdd抛出异常的情况', () => {
    jest.mock('./mockAdd', () => ({
      mockAdd: jest.fn().mockImplementation(() => {
        throw new Error('模拟异常');
      })
    }));
    const result = add(1, 2);
    expect(result).toBeUndefined();
  });
});

集成测试

集成测试通常用于验证不同模块之间的交互,确保它们能够正确协作。Jest可以很好地支持集成测试,可以与库如React Testing Library结合使用,进行端到端测试。

示例代码:

// App.js
import React from 'react';

function App() {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  );
}

export default App;

// App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

describe('App组件测试', () => {
  it('应能正确渲染Hello, World!文本', () => {
    render(<App />);
    const textElement = screen.getByText(/Hello, World!/i);
    expect(textElement).toBeInTheDocument();
  });
});
Jest调试技巧

调试Jest测试

调试Jest测试时,可以使用以下几种方法:

  • 内联调试:在测试代码中添加console.log或其他调试语句,输出中间结果。
  • 调试工具:使用Chrome DevTools或其他调试工具,在测试运行时进行调试。
  • Jest自带的调试选项:Jest提供了一些调试选项,如--debug--runInBand,可以在命令行中使用这些选项进行调试。

示例代码:

npm run test -- --runInBand

这将使测试在单个工作进程内执行,便于调试。

测试覆盖率分析

Jest提供了测试覆盖率分析功能,可以帮助开发者了解哪些代码已经被测试覆盖。测试覆盖率报告可以以HTML或JSON格式生成。

示例代码:

npm run test -- --coverage

这将生成测试覆盖率报告,并输出到coverage目录中。

解决常见问题与报错

在使用Jest进行测试时,可能会遇到一些常见问题和报错,以下是一些常见问题及其解决方法:

  • 错误:未找到模块:确保所有依赖都已正确安装,并且模块路径正确。
  • 错误:未找到测试文件:确保测试文件路径正确,且文件名符合Jest的命名规则。
  • 未通过的测试:审查测试代码和被测试代码,确保逻辑正确,断言方法使用正确。

示例代码:

// add.test.js
import add from './add';

describe('add函数测试', () => {
  it('应能正确执行add', () => {
    expect(add(1, 2)).toBe(3);
  });

  it('应能正确处理负数相加', () => {
    expect(add(-1, -2)).toBe(-3);
  });

  it('应能正确处理大数相加', () => {
    expect(add(Number.MAX_SAFE_INTEGER, 1)).toBe(Number.MAX_SAFE_INTEGER + 1);
  });
});
Jest实战案例

项目中使用Jest的示例

假设我们有一个简单的待办事项应用,包含一个待办事项列表和一个添加事项的函数。我们可以使用Jest来编写单元测试和集成测试。

单元测试

我们首先编写单元测试来验证添加事项函数的逻辑是否正确。

// todo.test.js
import { addTodo, getTodoList } from './todo';

describe('待办事项模块测试', () => {
  it('应能正确添加待办事项', () => {
    addTodo('完成作业');
    addTodo('做菜');
    expect(getTodoList()).toEqual(['完成作业', '做菜']);
  });

  it('应能正确处理重复事项', () => {
    addTodo('做菜');
    addTodo('做菜');
    expect(getTodoList()).toEqual(['做菜']);
  });
});

集成测试

集成测试可以验证整个应用的功能是否正确,例如,可以测试添加事项和渲染事项列表的交互。

// App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

describe('App组件测试', () => {
  it('应能正确渲染待办事项列表', () => {
    render(<App />);
    const todoList = screen.getByText(/待办事项列表/i);
    expect(todoList).toBeInTheDocument();
  });

  it('应能正确处理添加事项的功能', () => {
    render(<App />);
    const addButton = screen.getByText(/添加事项/i);
    const input = screen.getByLabelText(/事项内容/i);
    input.value = '完成作业';
    addButton.click();
    expect(screen.getByText('完成作业')).toBeInTheDocument();
  });
});

从实践中学到的经验

在实际项目中使用Jest进行测试时,需要注意以下几点:

  • 保持测试代码的可读性和可维护性:使用清晰的描述和标题,避免冗余的测试代码。
  • 避免过度测试:不要编写重复的测试,只编写必要的测试用例。
  • 使用模拟和间谍函数:模拟复杂的依赖和外部调用,使测试更加简单和独立。
  • 持续集成和持续测试:将Jest测试集成到CI/CD流程中,确保每次代码提交都能触发测试。

Jest与其他工具的配合

在实际项目中,Jest可以与其他工具结合使用,提高测试的效果和效率。

  • ESLint:使用ESLint进行代码风格检查和潜在错误的检测。
  • React Testing Library:用于React组件的端到端测试。
  • Jest和Coveralls:使用Jest进行测试,并使用Coveralls进行测试覆盖率分析。

示例代码:

// .eslintrc.js
module.exports = {
  parser: '@babel/eslint-parser',
  extends: [
    'eslint:recommended',
    'plugin:react/recommended'
  ],
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 2018,
    sourceType: 'module'
  },
  rules: {
    'react/react-in-jsx-scope': 'off',
    'react/prop-types': 'off'
  },
  env: {
    browser: true,
    node: true
  }
};
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消