搭建Vue3组件库:第五章 Jest进行前端单元测试

简介: 单元测试是软件质量的重要保证。本章节介绍Jest测试框架。

单元测试是软件质量的重要保证。在 Github 上挑选一款软件,单元测试覆盖率是评价软件成熟度的一个重要指标。通常成熟可靠的开源产品都有完善的单元测试,并且覆盖率可以达到 80% 以上。

本章任务

  • 搭建Jest环境
  • 编写有关Jest的函数
  • 引入DOM仿真,完成一个前端页面测试

task1】搭建 Jest环境

  • 安装依赖
npm i jest -g
  • 根目录创建add.js测试文件

文件名:add.js

const add = (a, b) => a + b;
module.exports = add;
  • 编写Jest测试函数

文件名:src/tests/add.test.js

const add = require("../../add");

describe("测试Add函数", () => {
  test("add(1,2) === 3", () => {
    expect(add(1, 2)).toBe(3);
  });
  test("add(1,1) === 2", () => {
    expect(add(1, 1)).toBe(2);
  });
});
  • 运行jest测试命令
jest

Jest会自动到项目里面查找所有测试用例文件。

如果你想不想使用全局的jest:

pnpm i jest -D

测试命令需要加上npx

npx jest
  • 控制台查看结果
 PASS  tests/add.test.js
  测试Add函数
    √ add(1,2) === 3 (1 ms)                                                                                                               
    √ add(1,1) === 2                                                                                                                      
                                                                                                                                          
Test Suites: 1 passed, 1 total                                                                                                            
Tests:       2 passed, 2 total                                                                                                            
Snapshots:   0 total
Time:        0.483 s
Ran all test suites.

至此测试环境可用。


task2】使用Jest的Mock模拟无法执行的函数

如果被测试的代码,调用了一个网络请求 API ,比如 axios,但是那个网络地址并不存在或者没有联网,这个时候应该如何测试呢?

  • 安装axios开发依赖
pnpm i axios -D
  • 根目录创建fetch.js测试文件
const axios = require('axios')
exports.getData = () => axios.get('/abc/bcd')
单元测试是针对开发的最小单位展开的测试,通常是函数。遇到函数调用函数的情况,比如 A 函数调用 B 函数,测试的主体是 A 函数,B 函数应该与测试无关,应该孤立 B 函数来测试 A 函数。

对于上面的 getData 函数来讲,调用了 axios.get 函数,应该模拟一个 axios.get 函数来替换掉原有的axios.get 函数。模拟的 axios.get 函数不会调用网络请求,只具有根据输入返回相应结果的功能。这个就是Mock函数。

单元测试的任务是验证 getData 函数的功能是否正确,而不是axios.get 函数或者网络接口是否正确。

  • 编写测试文件

首先使用 jest.mock创建一个 axios 的 mock 对象。实际上就是创建了一个虚拟的 axios 函数替换原函数。然后通过 mockResolvedValue 定义调用 axios.get 函数的返回值。这个时候再调用getData() 方法的时候 ,函数内部的 axios.get 是虚拟 mock 函数。调用时不会发生真正的网络请求,只会返回预定的结果。

文件名:src/tests/fetch.test.js

const { getData } = require("../fetch");
const axios = require("axios");
jest.mock("axios");
it("fetch", async () => {
  // 模拟第一次接收到的数据
  axios.get.mockResolvedValueOnce("123");
  // 模拟每一次接收到的数据
  axios.get.mockResolvedValue("456");
    
  const data1 = await getData();
  const data2 = await getData();
  expect(data1).toBe("123");
  expect(data2).toBe("456");
});
  • 执行测试命令
jest
  • 控制台查看结果
 PASS  src/tests/add.test.js
 PASS  src/tests/fetch.test.js
                                                                                                                                          
Test Suites: 2 passed, 2 total                                                                                                            
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.707 s, estimated 1 s
Ran all test suites.

jest.fn()

jest.fn()是创建Mock函数最简单的方式,如果没有定义函数内部的实现,jest.fn()会返回undefined作为返回值。

test('测试jest.fn()调用', () => {
  let mockFn = jest.fn();
  let result = mockFn(1, 2, 3);

  // 断言mockFn的执行后返回undefined
  expect(result).toBeUndefined();
  // 断言mockFn被调用
  expect(mockFn).toBeCalled();
  // 断言mockFn被调用了一次
  expect(mockFn).toBeCalledTimes(1);
  // 断言mockFn传入的参数为1, 2, 3
  expect(mockFn).toHaveBeenCalledWith(1, 2, 3);
})

task3】测试前端页面

前端程序和纯 JS 的区别在于运行时不同。前端程序运行于浏览器端,会直接调用 Dom 对象。但是 Node 中并没有 Dom 模型。

解决的办法有两个 :

  • 将测试用例放到浏览器中运行;
  • dom 仿真模拟一个 dom 对象。

最佳的选择是后者,因为你的测试程序会放到不同的环境中执行,你不可能要求 CI 服务器中也有浏览器。而且放入浏览器再执行,效率也是一个大问题。

模拟一个 dom 对象需要用到 dom 仿真,常见的有 jsdomhappydom

  • 安装依赖
pnpm i jsdom -D
  • 配置jsdom

在 jest 中引入 jsdom ,需要编写一个 jsdom-config.js 文件。

文件名:jsdom-config.js

// jsdom-config.js
const jsdom = require('jsdom') // eslint-disable-line
const { JSDOM } = jsdom

const dom = new JSDOM('<!DOCTYPE html><head/><body></body>', {
  url: 'http://localhost/',
  referrer: 'https://example.com/',
  contentType: 'text/html',
  userAgent: 'Mellblomenator/9000',
  includeNodeLocations: true,
  storageQuota: 10000000,
})
global.window = dom.window
global.document = window.document
global.navigator = window.navigator
  • 编写dom.js被测文件

函数中创建一个 div 元素。

文件名:dom.js

exports.generateDiv = () => {
  const div = document.createElement("div");
  div.className = "c1";
  document.body.appendChild(div);
};
  • 编写dom的测试文件

在测试程序中,被测试函数创建了一个 div 元素,接着就可以在 dom 仿真中获取 div 元素了。也可以用断言来判断代码功能是否正常。

文件名:src/tests/dom.test.js

const { generateDiv } = require('../dom') 
require('../../jsdom-config')
describe('Dom测试', () => {
    
    test('测试dom操作', () => {
        generateDiv()
        expect(document.getElementsByClassName('c1').length).toBe(1)
    })
})
  • 执行jest命令
jest
  • 控制台查看结果
 PASS  src/tests/fetch.test.js
 PASS  src/tests/add.test.js
 PASS  src/tests/dom.test.js
                                                                                                                                          
Test Suites: 3 passed, 3 total                                                                                                            
Tests:       5 passed, 5 total
Snapshots:   0 total
Time:        1.647 s
Ran all test suites.

这个就是 dom 测试。前端常用的 Vue React 程序也都可以使用这样的方法进行测试。

相关文章
|
4月前
|
人工智能 前端开发 测试技术
如何让AI帮你做前端自动化测试?我们这样落地了
本文介绍了一个基于AI的UI自动化测试框架在专有云质量保障中的工程化实践。
1940 21
如何让AI帮你做前端自动化测试?我们这样落地了
|
8月前
|
前端开发 API 开发者
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
本文由黑臂麒麟(6年前端经验)撰写,介绍ArkTS开发中的常用基础组件与布局组件。基础组件包括Text、Image、Button等,支持样式设置如字体颜色、大小和加粗等,并可通过Resource资源引用统一管理样式。布局组件涵盖Column、Row、List、Grid和Tabs等,支持灵活的主轴与交叉轴对齐方式、分割线设置及滚动事件监听。同时,Tabs组件可实现自定义样式与页签切换功能。内容结合代码示例,适合初学者快速上手ArkTS开发。参考华为开发者联盟官网基础课程。
707 75
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
|
7月前
|
JavaScript 前端开发 API
|
9月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
584 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
10月前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
366 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
前端开发 JavaScript 测试技术
前端测试技术中,如何提高集成测试的效率?
前端测试技术中,如何提高集成测试的效率?
|
9月前
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
658 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
|
9月前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
490 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
10月前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
344 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
12月前
|
监控 前端开发 数据可视化
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生
@icraft/player-react 是 iCraft Editor 推出的 React 组件库,旨在简化3D数字孪生场景的前端集成。它支持零配置快速接入、自定义插件、丰富的事件和方法、动画控制及实时数据接入,帮助开发者轻松实现3D场景与React项目的无缝融合。
769 9
3D架构图软件 iCraft Editor 正式发布 @icraft/player-react 前端组件, 轻松嵌入3D架构图到您的项目,实现数字孪生