react+jest+enzyme配置及编写前端单元测试UT

简介: react+jest+enzyme配置及编写前端单元测试UT

原文合集地址如下,有需要的朋友可以关注

本文地址

合集地址

@[TOC]

安装及配置

  1. 安装相关库:
    首先,使用npm或yarn安装所需的库。
npm install --save-dev jest enzyme enzyme-adapter-react-16 enzyme-to-json
  1. 配置Jest:
    在项目根目录下创建一个jest.config.js文件,并配置Jest。
// jest.config.js
module.exports = {
   
  setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
  testEnvironment: 'jsdom',
  moduleNameMapper: {
   
    '\\.(css|less)$': 'identity-obj-proxy',
  },
};

在上述配置中,设置了setupFilesAfterEnvsrc/setupTests.js,指定了测试环境为jsdom,并设置了模块名称映射以处理CSS和LESS文件。

  1. 创建setupTests.js文件:
    在项目的src目录下创建一个setupTests.js文件,并进行Enzyme的初始化和配置。
// src/setupTests.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({
    adapter: new Adapter() });

在上述代码中,导入Enzyme和Enzyme适配器,并使用适配器初始化Enzyme。

  1. 编写测试用例:
    在测试目录中创建一个与要测试的组件对应的测试文件,并编写测试用例。
import React from 'react';
import {
    mount } from 'enzyme';
import YourComponent from '../YourComponent';

describe('YourComponent', () => {
   
  it('renders correctly', () => {
   
    const component = mount(<YourComponent />);
    expect(component.find('.your-class').text()).toBe('Hello World');
  });
});

在上述代码中,使用mount方法来渲染组件,并使用Enzyme提供的API来查找组件中的元素,并进行断言验证。

  1. 运行测试:
    在终端中运行测试命令,以执行测试用例。
npm run test

Jest将自动查找并执行项目中以.test.js.spec.js结尾的文件中的测试用例。

enzyme渲染

Enzyme提供了三种常用的渲染方式,分别是shallowmountrender。这些渲染方式在测试组件时具有不同的特点和用途。

  1. shallow 渲染:
    shallow 渲染是Enzyme的浅层渲染方式,它仅渲染被测试组件本身,而不渲染其子组件。
import {
    shallow } from 'enzyme';
import YourComponent from '../YourComponent';

test('测试组件渲染', () => {
   
  const wrapper = shallow(<YourComponent />);
  // 对被测试组件进行断言和验证
});

使用shallow渲染时,被测试组件的子组件将被替换为占位符,并且无法直接访问子组件。这使得测试更加轻量且快速,适用于对被测试组件本身的行为进行测试。

  1. mount 渲染:
    mount 渲染是Enzyme的全渲染方式,它会将被测试组件及其子组件完全渲染到真实的DOM中。这使得可以模拟实际的组件嵌套和交互,并对其进行全面的测试。
import {
    mount } from 'enzyme';
import YourComponent from '../YourComponent';

test('测试组件渲染', () => {
   
  const wrapper = mount(<YourComponent />);
  // 对被测试组件及其子组件进行断言和验证
});

使用mount渲染时,被测试组件及其子组件将在真实的DOM中进行渲染和交互。这使得可以测试组件的交互、生命周期方法和子组件的行为。

  1. render 渲染:
    render 渲染是Enzyme的静态渲染方式,它将组件渲染为静态的HTML字符串,不涉及真实的DOM操作。这使得可以对组件的输出进行快照测试,以验证其渲染结果是否符合预期。
import {
    render } from 'enzyme';
import YourComponent from '../YourComponent';

test('测试组件渲染', () => {
   
  const wrapper = render(<YourComponent />);
  // 对组件输出的HTML进行断言和验证
});

使用render渲染时,被测试组件及其子组件将以静态HTML字符串的形式输出,可以方便地进行快照测试。
下面的例子中使用到的渲染方式只是举例,结合实际情况使用mount、shalldow或者render都是可以的。

测试技巧

一、常见测试

  1. 示例:测试组件渲染和属性传递
    假设有一个简单的React组件 Button,接收一个label属性,并在按钮上显示该标签。可以编写一个测试用例来验证组件是否正确渲染和传递属性。
import React from 'react';
import {
    shallow } from 'enzyme';
import Button from '../Button';

describe('Button', () => {
   
  it('renders correctly with label prop', () => {
   
    const label = 'Click me';
    const wrapper = shallow(<Button label={
   label} />);
    expect(wrapper.text()).toBe(label);
  });
});

在上述例子中,使用shallow渲染方法来渲染Button组件,并使用expecttoBe断言验证按钮上的文本是否与传递的标签相匹配。

  1. 示例:模拟事件处理
    假设有一个表单组件 LoginForm,其中包含一个提交按钮。可以编写一个测试用例来模拟按钮点击事件,并验证相应的事件处理函数是否被调用。
import React from 'react';
import {
    mount } from 'enzyme';
import LoginForm from '../LoginForm';

describe('LoginForm', () => {
   
  it('calls onSubmit handler on button click', () => {
   
    const onSubmit = jest.fn();
    const wrapper = mount(<LoginForm onSubmit={
   onSubmit} />);
    wrapper.find('button').simulate('click');
    expect(onSubmit).toHaveBeenCalledTimes(1);
  });
});

在上述例子中,使用mount渲染方法来渲染LoginForm组件,并使用simulate方法模拟按钮的点击事件。然后,使用expecttoHaveBeenCalledTimes断言验证onSubmit函数是否被调用了一次。

  1. 示例:异步操作的处理
    如果组件中包含异步操作,可以使用async/awaitdone回调函数来处理异步测试。
import React from 'react';
import {
    mount } from 'enzyme';
import AsyncComponent from '../AsyncComponent';

describe('AsyncComponent', () => {
   
  it('renders data correctly after fetching', async () => {
   
    const fetchData = () => {
   
      return new Promise((resolve) => {
   
        setTimeout(() => {
   
          resolve('Data');
        }, 1000);
      });
    };

    const wrapper = mount(<AsyncComponent fetchData={
   fetchData} />);
    expect(wrapper.text()).toBe('Loading...');

    await Promise.resolve(); // 等待异步操作完成
    wrapper.update();

    expect(wrapper.text()).toBe('Data');
  });
});

在上述例子中,使用await关键字等待异步操作的完成,并使用wrapper.update()手动更新组件,以便正确渲染异步操作后的数据。

二、触发ant design组件

使用Ant Design的组件时,可以通过模拟事件或直接调用组件的方法来触发各种操作。下面是一些常见组件的触发方法示例:

  1. Input 输入框:
import {
    mount } from 'enzyme';
import {
    Input } from 'antd';

test('触发Input输入', () => {
   
  const wrapper = mount(<Input />);
  // 模拟输入
  wrapper.find('input').simulate('change', {
    target: {
    value: 'Hello' } });
  // 模拟回车
  wrapper.find('input').simulate('keydown', {
    keyCode: 13, which: 13 }
});
// 模拟失去焦点
test('模拟输入框失去焦点', () => {
   
  const onBlur = jest.fn(); // 失去焦点时调用的函数

  const wrapper = mount(<YourComponent onBlur={
   onBlur} />);

  // 找到输入框元素,并触发失去焦点事件
  wrapper.find('input').simulate('blur');

  wrapper(onBlur).toHaveBeenCalled();
});

在上述例子中,使用simulate方法模拟输入框的change事件,并传递了一个模拟的event对象,其中target.value表示输入的值。

  1. Select 选择器:
import {
    mount } from 'enzyme';
import {
    Select } from 'antd';

test('直接调用Select方法更新选项', () => {
   
  const wrapper = mount(
    <Select>
      <Select.Option value="option1">Option 1</Select.Option>
      <Select.Option value="option2">Option 2</Select.Option>
    </Select>
  );

  const selectInstance = wrapper.find('Select').instance();

  // 更新选项
  selectInstance.updateOptions([
    {
    value: 'option3', label: 'Option 3' },
    {
    value: 'option4', label: 'Option 4' },
  ]);
});

在上述例子中,使用 simulate 方法模拟点击下拉菜单按钮的 mousedown 事件,然后模拟点击第一个选项的 click 事件来选择该选项。

  1. Checkbox 复选框:
import { mount } from 'enzyme';
import { Checkbox } from 'antd';

test('触发Checkbox选择', () => {
  const wrapper = mount(<Checkbox>Checkbox</Checkbox>);
  wrapper.find('input').simulate('change', { target: { checked: true } });
});

在上述例子中,使用simulate方法模拟复选框的change事件,并传递了一个模拟的event对象,其中target.checked表示复选框的选中状态。

  1. Dropdown 下拉菜单:
import {
    mount } from 'enzyme';
import {
    Dropdown, Menu } from 'antd';

test('触发Dropdown菜单', () => {
   
  const menu = (
    <Menu>
      <Menu.Item key="1">Option 1</Menu.Item>
      <Menu.Item key="2">Option 2</Menu.Item>
    </Menu>
  );
  const wrapper = mount(<Dropdown overlay={
   menu}><a href="#">Dropdown</a></Dropdown>);
  wrapper.find('a').simulate('click');
});

在上述例子中,使用simulate方法模拟下拉菜单的触发事件,例如click事件。

  1. 模拟文件上传
    在React中,由于安全性的限制,不能直接模拟文件上传的完整流程。但是,可以通过模拟触发change事件来模拟用户选择文件的行为。这样可以触发相应的文件上传逻辑。

以下是一个示例代码,演示了如何使用simulate方法来模拟文件上传:

import {
    mount } from 'enzyme';

test('模拟文件上传', () => {
   
  const onFileUpload = jest.fn(); // 模拟文件上传时调用的函数

  const wrapper= mount(<YourComponent onFileUpload={
   onFileUpload} />);

  // 创建一个模拟的File对象
  const file = new File(['文件内容'], 'filename.txt', {
    type: 'text/plain' });

  // 创建一个模拟的事件对象,设置target.files为模拟的File对象
  const event = {
   
    target: {
    files: [file] },
  };

  // 找到文件上传的input元素,并触发change事件
  wrapper.find('input[type="file"]').simulate('change', event);

  expect(onFileUpload).toHaveBeenCalledWith(file);
});

在上述代码中,创建了一个模拟的File对象,并将其作为事件对象的target.files属性。然后,使用simulate方法触发了一个change事件,模拟文件选择的操作。最后,使用expect断言来验证回调函数onFileUpload是否被调用,并传递了模拟的文件对象作为参数。

这些是一些常见Ant Design组件的触发方法示例。根据具体的组件和需求,可以使用适当的方法来模拟事件触发或直接调用组件的方法。

三、使用redux组件

当编写涉及Redux的组件的单元测试时,可以采取以下措施以确保测试不会报错:

  1. 模拟Redux Store:
    在测试中,可以创建一个模拟的Redux Store,并将其传递给组件作为属性。可以使用类似于redux-mock-store的库来创建模拟的Store。
import React from 'react';
import {
    shallow } from 'enzyme';
import configureMockStore from 'redux-mock-store';
import YourComponent from '../YourComponent';

const mockStore = configureMockStore();
const initialState = {
   
  // 初始状态
};
const store = mockStore(initialState);

describe('YourComponent', () => {
   
  it('renders without errors', () => {
   
    const wrapper = shallow(<YourComponent store={
   store} />);
    expect(wrapper).toBeTruthy();
  });
});

在上述例子中,使用redux-mock-store库创建了一个模拟的Store,并将其传递给YourComponent作为属性。

  1. 使用Provider组件:
    在测试中,使用Redux的Provider组件将模拟的Store包装在组件的外部。这样可以确保组件在测试中能够访问到Redux的状态和行为。
import React from 'react';
import {
    shallow } from 'enzyme';
import {
    Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import YourComponent from '../YourComponent';

const mockStore = configureMockStore();
const initialState = {
   
  // 初始状态
};
const store = mockStore(initialState);

describe('YourComponent', () => {
   
  it('renders without errors', () => {
   
    const wrapper = shallow(
      <Provider store={
   store}>
        <YourComponent />
      </Provider>
    );
    expect(wrapper).toBeTruthy();
  });
});

在上述例子中,使用Redux的Provider组件将模拟的Store包装在YourComponent的外部,以确保组件在测试中能够正确连接到Redux。

  1. 测试Redux相关的行为:
    在编写单元测试时,除了测试组件的渲染和行为外,还可以编写专门测试Redux相关行为的测试用例。例如,测试Redux的action创建函数、reducer函数和异步操作的处理等。

    四、使用路由的组件

    当编写涉及React Router的组件的单元测试时,可以采取以下措施来处理受到影响的组件:

  2. 使用MemoryRouter:
    在测试中,使用MemoryRouter来包装被测试的组件。MemoryRouter是React Router提供的一个用于测试的特殊路由器组件,它在内存中维护路由状态,不会对浏览器URL进行实际更改。

import React from 'react';
import {
    shallow } from 'enzyme';
import {
    MemoryRouter } from 'react-router-dom';
import YourComponent from '../YourComponent';

describe('YourComponent', () => {
   
  it('renders without errors', () => {
   
    const wrapper = shallow(
      <MemoryRouter>
        <YourComponent />
      </MemoryRouter>
    );
    expect(wrapper).toBeTruthy();
  });
});

在上述例子中,使用MemoryRouter将被测试的组件包装在内部,以便在测试中模拟路由。

  1. 使用StaticRouter:
    如果组件使用了Server-Side Rendering(SSR),可以使用StaticRouter来模拟服务器端渲染的路由。
import React from 'react';
import {
    shallow } from 'enzyme';
import {
    StaticRouter } from 'react-router-dom';
import YourComponent from '../YourComponent';

describe('YourComponent', () => {
   
  it('renders without errors', () => {
   
    const context = {
   };
    const wrapper = shallow(
      <StaticRouter location="/your-path" context={
   context}>
        <YourComponent />
      </StaticRouter>
    );
    expect(wrapper).toBeTruthy();
  });
});

在上述例子中,使用StaticRouter来模拟服务器端渲染的路由,并通过location属性设置当前的路径。

  1. 使用BrowserRouterRouter
    如果组件使用了BrowserRouter或自定义的Router组件,可以在测试中直接使用这些组件,并通过history属性模拟路由历史记录。
    ```javascript
    import React from 'react';
    import { shallow } from 'enzyme';
    import { BrowserRouter, Router } from 'react-router-dom';
    import YourComponent from '../YourComponent';
    import { createMemoryHistory } from 'history';

describe('YourComponent', () => {
it('renders without errors', () => {
const history = createMemoryHistory();
const wrapper = shallow(



);
expect(wrapper).toBeTruthy();
});
});


在上述例子中,使用`createMemoryHistory`创建一个内存中的`history`对象,并将其通过`Router`组件传递给被测试的组件。

## 五、mock接口网络请求
1. mock 接口请求
```javascript
// @/servise/XXX 是我自己封装的功能请求的相对地址
// 方法一
jest.mock('@/servise/XXX', ()=>({
getData: Promise.resove({res:{}})
));
// 方法二
import service from '@/service/XXX';
service.getData= ()=>Promise.resolve({res:{}})

2.自定义模拟的请求和返回数据

import YourComponent from '../YourComponent';
import axios from 'axios';

jest.mock('axios');

describe('YourComponent', () => {
   
  it('should handle API request', async () => {
   
    // 自定义模拟的请求和返回数据
    const mockResponseData = {
    name: 'John Doe' };
    axios.get.mockResolvedValue({
    data: mockResponseData });

    // 执行组件中的接口请求
    const component = new YourComponent();
    await component.fetchData();

    // 验证结果
    expect(component.data).toEqual(mockResponseData);
  });
});

六、mock不需要的子组件

要 mock 掉不需要的子组件,可以使用 jest.mockjest.fn(或 jest.mock 中的 jest.fn)来模拟子组件的导入。

下面是一个示例,演示如何 mock 掉不需要的子组件:

import React from 'react';
import {
    shallow } from 'enzyme';
import ParentComponent from '../ParentComponent';
import ChildComponent from '../ChildComponent';

jest.mock('../ChildComponent', () => jest.fn(() => null));

describe('ParentComponent', () => {
   
  it('should render without the ChildComponent', () => {
   
    const wrapper = shallow(<ParentComponent />);
    expect(wrapper.find(ChildComponent)).toHaveLength(0);
  });
});

在上述例子中,使用 jest.mock 来模拟 ChildComponent 的导入,并将其替换为一个匿名的空函数组件。这样,在渲染 ParentComponent 时,ChildComponent 实际上会被替换为一个空的函数组件。

然后,可以使用 shallow 来浅渲染 ParentComponent,并使用 expect 断言验证 ChildComponent 是否没有被渲染。

这样,就成功地 mock 掉了不需要的子组件,从而使测试集中关注于 ParentComponent 的逻辑和行为,而不会受到实际的子组件的影响。

目录
相关文章
|
10天前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
36 9
|
5天前
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
12天前
|
前端开发 JavaScript 测试技术
前端小白逆袭之路:如何快速掌握前端测试技术,确保代码质量无忧!
【10月更文挑战第30天】前端开发技术迭代迅速,新手如何快速掌握前端测试以确保代码质量?本文将介绍前端测试的基础知识,包括单元测试、集成测试和端到端测试,以及常用的测试工具如Jest、Mocha、Cypress等。通过实践和学习,你也能成为前端测试高手。
31 4
|
14天前
|
缓存 前端开发 JavaScript
前端性能优化:Webpack与Babel的进阶配置与优化策略
【10月更文挑战第28天】在现代Web开发中,Webpack和Babel是不可或缺的工具,分别负责模块打包和ES6+代码转换。本文探讨了它们的进阶配置与优化策略,包括Webpack的代码压缩、缓存优化和代码分割,以及Babel的按需引入polyfill和目标浏览器设置。通过这些优化,可以显著提升应用的加载速度和运行效率,从而改善用户体验。
35 6
|
10天前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
|
16天前
|
缓存 监控 前端开发
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第26天】前端工程化是现代Web开发的重要趋势,通过将前端代码视为工程来管理,提高了开发效率和质量。本文详细对比了Webpack和Gulp两大主流构建工具的选择与配置优化,并提供了具体示例代码。Webpack擅长模块化打包和资源管理,而Gulp则在任务编写和自动化构建方面更具灵活性。两者各有优势,需根据项目需求进行选择和优化。
46 7
|
15天前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
31 2
|
15天前
|
前端开发 JavaScript Android开发
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第27天】React Native 是跨平台开发领域的佼佼者,凭借其独特的跨平台能力和高效的开发体验,成为许多开发者的首选。本文探讨了 React Native 的优势与挑战,包括跨平台开发能力、原生组件渲染、性能优化及调试复杂性等问题,并通过代码示例展示了其实际应用。
43 2
|
15天前
|
缓存 前端开发 JavaScript
前端工程化:Webpack与Gulp的构建工具选择与配置优化
【10月更文挑战第27天】在现代前端开发中,构建工具的选择对项目的效率和可维护性至关重要。本文比较了Webpack和Gulp两个流行的构建工具,介绍了它们的特点和适用场景,并提供了配置优化的最佳实践。Webpack适合大型模块化项目,Gulp则适用于快速自动化构建流程。通过合理的配置优化,可以显著提升构建效率和性能。
29 2
|
16天前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
27 2

热门文章

最新文章