vitest 单元测试配合@vue/test-utils 之 axios 篇

what is vitest & VueTestUtils & axios

vitest 是由 vite 提供支持的极速单元测试框架,VueTestUtils 是 Vue.js 的官方测试实用程序库,Axios 是一个基于 promise 的网络请求库,以上均为各自官网对其的描述

demo

项目中使用 axios 是非常常见的,所以我们可以对他做一个单元测试,在 test-utils 的文档中提到除了 jest.mock()还可以使用axios-mock-adapter,其实我们可以使用 vitest 的 vi.mock()来完成,但是翻看了axios-mock-adapter库的示例后,明白了官方的推荐并不是不无道理,所以此篇 demo 引入该库来完成

// component
<script setup lang="ts">
import { ref } from 'vue'
import MockAdapter from 'axios-mock-adapter'
import axios from 'axios'

const name = ref('李四')
const mock = new MockAdapter(axios)
const resulst = { name: '张三', age: 18 }
mock.onGet('/user').reply(200, resulst)
const handleRequestChange = () => {
  axios.get('/user').then(res => {
    name.value = res.data.name
  })
}
</script>

<template>
  <span>{{ name }}</span>
  <button @click="handleRequestChange">get</button>
</template>
import { describe, it, expect, vi } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import axios from 'axios'
import RequestService from '@/views/RequestService.vue'
describe('axios-tets', () => {
  it('tets1', async () => {
    const spy = vi.spyOn(axios, 'get')
    const wrapper = mount(RequestService)
    await wrapper.find('button').trigger('click')
    expect(spy).toHaveBeenCalledTimes(1)
    expect(spy).toHaveBeenCalledWith('/user')
  })
  it('test2', async () => {
    const wrapper = mount(RequestService)
    expect(wrapper.find('span').text()).toContain('李四')
    await wrapper.find('button').trigger('click')
    await flushPromises()
    expect(wrapper.find('span').text()).toContain('张三')
  })
})
  1. demo 由两部分组成,组件和测试文件
  2. 组件的逻辑非常简单,使用axios-mock-adapter创建一个 mock 数据,模拟 get 请求,页面有一个初始值,按钮按下发送网络请求,更新页面的数据
  3. 测试文件有两组测试,第一组和上一篇测试 router 里面的编程式路由很相似,首先监听 axios 的 get 方法,然后挂载组件,触发组件的点击事件,然后断言函数是否被调用过指定次数、是否调用过并且传入指定参数
  4. 第二组就更加熟悉了,之前的三篇都做过类似的测试,挂载组件然后查找元素,断言元素的文本是否与预期值一致,flushPromises方法会刷新所有已解决的 promise 程序

tips

同样的这是一个简单的 demo,但它还是有很多值得注意的知识点

  • axios-mock-adapter 一个 axios 适配器,可以轻松模拟请求,文中只用到了 get 请求,但其实他有着丰富的功能,无论是单元测试还是实际开发中后端没有开发出接口需要自己模拟数据时都很适用,推荐~~
  • vi.mock 可以使用 vi.spyOn()监听 axios 的 get 请求来跟踪 mock 执行
const result = {name: '张三', age: 18}
vi.spyOn(axios, 'get').mockResolvedValue(result)
// mockResolvedValue 异步函数被调用时接收一个resolve值

其他文章

vitest 单元测试配合@vue/test-utils 之组件单元测试篇
vitest 单元测试配合@vue/test-utils 之 pinia 篇
vitest 单元测试配合@vue/test-utils 之 router 篇

PS D:\聚合四方\pcAdmin> npm outdated Package Current Wanted Latest Location Depended by @babel/core 7.0.0 7.0.0 7.27.1 node_modules/@babel/core pcAdmin @vue/cli-plugin-babel 3.5.3 3.5.3 5.0.8 node_modules/@vue/cli-plugin-babel pcAdmin @vue/cli-plugin-eslint 3.12.1 3.12.1 5.0.8 node_modules/@vue/cli-plugin-eslint pcAdmin @vue/cli-plugin-unit-jest 4.5.19 4.5.19 5.0.8 node_modules/@vue/cli-plugin-unit-jest pcAdmin @vue/cli-service 4.5.19 4.5.19 5.0.8 node_modules/@vue/cli-service pcAdmin @vue/test-utils 1.0.0-beta.29 1.0.0-beta.29 2.4.6 node_modules/@vue/test-utils pcAdmin autoprefixer 9.8.8 9.8.8 10.4.21 node_modules/autoprefixer pcAdmin axios 0.18.1 0.18.1 1.9.0 node_modules/axios pcAdmin babel-core 7.0.0-bridge.0 7.0.0-bridge.0 6.26.3 node_modules/babel-core pcAdmin babel-eslint 10.0.1 10.0.1 10.1.0 node_modules/babel-eslint pcAdmin babel-jest 26.6.3 26.6.3 29.7.0 node_modules/babel-jest pcAdmin chalk 2.4.2 2.4.2 5.4.1 node_modules/chalk pcAdmin chokidar 2.1.5 2.1.5 4.0.3 node_modules/chokidar pcAdmin clipboard 2.0.4 2.0.4 2.0.11 node_modules/clipboard pcAdmin codemirror 5.45.0 5.45.0 6.0.1 node_modules/codemirror pcAdmin compression-webpack-plugin 6.1.2 6.1.2 11.1.0 node_modules/compression-webpack-plugin pcAdmin connect 3.6.6 3.6.6 3.7.0 node_modules/connect pcAdmin driver.js 0.9.5 0.9.5 1.3.6 node_modules/driver.js pcAdmin dropzone 5.5.1 5.5.1 6.0.0-beta.2 node_modules/dropzone pcAdmin echarts 4.2.1 4.2.1 5.6.0 node_modules/echarts pcAdmin eslint 5.15.3 5.15.3 9.27.0 node_modules/eslint pcAdmin eslint-plugin-vue 5.2.2 5.2.2 10.1.0 node_modules/eslint-plugin-vue pcAdmin file-saver 2.0.1 2.0.1 2.0.5 node_modules/file-saver pcAdmin fuse.js 3.4.4 3.4.4 7.1.0 node_modules/fuse.js pcAdmin html-webpack-plugin 3.2.0 3.2.0 5.6.3 node_modules/html-webpack-plugin pcAdmin husky 1.3.1 1.3.1 9.1.7 node_modules/husky pcAdmin js-cookie 2.2.0 2.2.0 3.0.5 node_modules/js-cookie pcAdmin jszip 3.2.1 3.2.1 3.10.1 node_modules/jszip pcAdmin less-loader 7.3.0 7.3.0 12.3.0 node_modules/less-loader pcAdmin lint-staged 8.1.5 8.1.5 16.0.0 node_modules/lint-staged pcAdmin mockjs 1.0.1-beta3 1.0.1-beta3 1.1.0 node_modules/mockjs pcAdmin normalize.css 7.0.0 7.0.0 8.0.1 node_modules/normalize.css pcAdmin path-to-regexp 2.4.0 2.4.0 8.2.0 node_modules/path-to-regexp pcAdmin sass-loader 7.3.1 7.3.1 16.0.5 node_modules/sass-loader pcAdmin screenfull 4.2.0 4.2.0 6.0.2 node_modules/screenfull pcAdmin script-ext-html-webpack-plugin 2.1.3 2.1.3 2.1.5 node_modules/script-ext-html-webpack-plugin pcAdmin serve-static 1.16.2 1.16.2 2.2.0 node_modules/serve-static pcAdmin showdown 1.9.1 1.9.1 2.1.0 node_modules/showdown pcAdmin sortablejs 1.8.4 1.8.4 1.15.6 node_modules/sortablejs pcAdmin svg-sprite-loader 4.1.3 4.1.3 6.0.11 node_modules/svg-sprite-loader pcAdmin svgo 1.2.0 1.2.0 3.3.2 node_modules/svgo pcAdmin terser-webpack-plugin 2.3.8 2.3.8 5.3.14 node_modules/terser-webpack-plugin pcAdmin vue-i18n 7.3.2 7.3.2 11.1.3 node_modules/vue-i18n pcAdmin vue-loader 17.4.2 15.11.1 17.4.2 node_modules/vue-loader pcAdmin vue-router 3.0.2 3.0.2 4.5.1 node_modules/vue-router pcAdmin vue-splitpane 1.0.4 1.0.4 1.0.6 node_modules/vue-splitpane pcAdmin vue-template-compiler 2.6.10 2.6.10 2.7.16 node_modules/vue-template-compiler pcAdmin vuedraggable 2.20.0 2.20.0 2.24.3 node_modules/vuedraggable pcAdmin vuex 3.1.0 3.1.0 4.1.0 node_modules/vuex pcAdmin webpack 4.47.0 4.47.0 5.99.9 node_modules/webpack 怎么修复
05-22
npm ls --dev npm warn config dev Please use --include=dev instead. healthkit-manage-front@6.24.12.100 C:\Users\x60102926\Desktop\HealthDeveloperService_manger\HealthKitManageFront ├── UNMET DEPENDENCY @element-plus/icons-vue@^2.0.10 ├── UNMET DEPENDENCY @kazupon/vue-i18n-loader@^0.3.0 ├── UNMET DEPENDENCY @types/diff@^5.0.9 ├── UNMET DEPENDENCY @types/webpack@^4.4.0 ├── UNMET DEPENDENCY @vue/cli-plugin-babel@^4.5.0 ├── UNMET DEPENDENCY @vue/cli-plugin-typescript@^4.5.15 ├── UNMET DEPENDENCY @vue/cli-service@4.5.0 ├── UNMET DEPENDENCY @vue/test-utils@^1.0.0-beta.20 ├── UNMET DEPENDENCY axios@1.8.4 ├── UNMET DEPENDENCY babel-core@7.0.0-bridge.0 ├── UNMET DEPENDENCY babel-plugin-component@^1.1.1 ├── UNMET DEPENDENCY colors-console@^1.0.3 ├── UNMET DEPENDENCY compressing@^1.5.1 ├── UNMET DEPENDENCY echarts@5.5.1 ├── UNMET DEPENDENCY element-plus@2.9.4 ├── UNMET DEPENDENCY lint-staged@^7.3.0 ├── UNMET DEPENDENCY moment@2.30.1 ├── UNMET DEPENDENCY node-sass@^4.13.0 ├── UNMET DEPENDENCY sass-loader@^7.0.1 ├── UNMET DEPENDENCY typescript@^4.9.4 ├── UNMET DEPENDENCY v-code-diff@1.12.0 ├── UNMET DEPENDENCY vue-cli-plugin-element@^1.0.0 ├── UNMET DEPENDENCY vue-echarts@6.7.3 ├── UNMET DEPENDENCY vue-facing-decorator@3.0.4 ├── UNMET DEPENDENCY vue-i18n@9.14.5 ├── UNMET DEPENDENCY vue-json-viewer@3.0.4 ├── UNMET DEPENDENCY vue-router@4.5.0 ├── UNMET DEPENDENCY vue@3.3.4 ├── UNMET DEPENDENCY webpack-bundle-analyzer@^3.0.3 └── UNMET DEPENDENCY xlsx@0.20.2 npm error code ELSPROBLEMS npm error missing: @element-plus/icons-vue@^2.0.10, required by healthkit-manage-front@6.24.12.100 npm error missing: @kazupon/vue-i18n-loader@^0.3.0, required by healthkit-manage-front@6.24.12.100 npm error missing: @types/diff@^5.0.9, required by healthkit-manage-front@6.24.12.100 npm error missing: @types/webpack@^4.4.0, required by healthkit-manage-front@6.24.12.100 npm error missing: @vue/cli-plugin-babel@^4.5.0, required by healthkit-manage-front@6.24.12.100 npm error missing: @vue/cli-plugin-typescript@^4.5.15, required by healthkit-manage-front@6.24.12.100 npm error missing: @vue/cli-service@4.5.0, required by healthkit-manage-front@6.24.12.100 npm error missing: @vue/test-utils@^1.0.0-beta.20, required by healthkit-manage-front@6.24.12.100 npm error missing: axios@1.8.4, required by healthkit-manage-front@6.24.12.100 npm error missing: babel-core@7.0.0-bridge.0, required by healthkit-manage-front@6.24.12.100 npm error missing: babel-plugin-component@^1.1.1, required by healthkit-manage-front@6.24.12.100 npm error missing: colors-console@^1.0.3, required by healthkit-manage-front@6.24.12.100 npm error missing: compressing@^1.5.1, required by healthkit-manage-front@6.24.12.100 npm error missing: echarts@5.5.1, required by healthkit-manage-front@6.24.12.100 npm error missing: element-plus@2.9.4, required by healthkit-manage-front@6.24.12.100 npm error missing: lint-staged@^7.3.0, required by healthkit-manage-front@6.24.12.100 npm error missing: moment@2.30.1, required by healthkit-manage-front@6.24.12.100 npm error missing: node-sass@^4.13.0, required by healthkit-manage-front@6.24.12.100 npm error missing: sass-loader@^7.0.1, required by healthkit-manage-front@6.24.12.100 npm error missing: typescript@^4.9.4, required by healthkit-manage-front@6.24.12.100 npm error missing: v-code-diff@1.12.0, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-cli-plugin-element@^1.0.0, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-echarts@6.7.3, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-facing-decorator@3.0.4, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-i18n@9.14.5, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-json-viewer@3.0.4, required by healthkit-manage-front@6.24.12.100 npm error missing: vue-router@4.5.0, required by healthkit-manage-front@6.24.12.100 npm error missing: vue@3.3.4, required by healthkit-manage-front@6.24.12.100 npm error missing: webpack-bundle-analyzer@^3.0.3, required by healthkit-manage-front@6.24.12.100 npm error missing: xlsx@0.20.2, required by healthkit-manage-front@6.24.12.100 npm error A complete log of this run can be found in: C:\Users\x60102926\AppData\Local\npm-cache\_logs\2025-09-16T07_14_18_740Z-debug-0.log
09-17
ERROR Failed to compile with 4 errors 15:39:58 error in ./node_modules/axios/lib/adapters/fetch.js Module parse failed: Unexpected token (161:6) You may need an appropriate loader to handle this file type. | const isCredentialsSupported = "credentials" in Request.prototype; | request = new Request(url, { | ...fetchOptions, | signal: composedSignal, | method: method.toUpperCase(), @ ./node_modules/axios/lib/adapters/adapters.js 4:0-38 @ ./node_modules/axios/lib/axios.js @ ./node_modules/axios/index.js @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/BrandList.vue @ ./src/components/BrandList.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./src/main.js error in ./node_modules/axios/lib/helpers/toURLEncodedForm.js Module parse failed: Unexpected token (17:4) You may need an appropriate loader to handle this file type. | return helpers.defaultVisitor.apply(this, arguments); | }, | ...options | }); | } @ ./node_modules/axios/lib/defaults/index.js 7:0-62 @ ./node_modules/axios/lib/axios.js @ ./node_modules/axios/index.js @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/BrandList.vue @ ./src/components/BrandList.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./src/main.js error in ./node_modules/axios/lib/platform/index.js Module parse failed: Unexpected token (5:2) You may need an appropriate loader to handle this file type. | | export default { | ...utils, | ...platform | } @ ./node_modules/axios/lib/defaults/index.js 8:0-44 @ ./node_modules/axios/lib/axios.js @ ./node_modules/axios/index.js @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/BrandList.vue @ ./src/components/BrandList.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./src/main.js error in ./node_modules/axios/lib/core/mergeConfig.js Module parse failed: Unexpected token (6:69) You may need an appropriate loader to handle this file type. | import AxiosHeaders from "./AxiosHeaders.js"; | | const headersToObject = (thing) => thing instanceof AxiosHeaders ? { ...thing } : thing; | | /** @ ./node_modules/axios/lib/axios.js 6:0-48 @ ./node_modules/axios/index.js @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/components/BrandList.vue @ ./src/components/BrandList.vue @ ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./src/App.vue @ ./src/App.vue @ ./src/main.js @ multi (webpack)-dev-server/client?http://localhost:8081 webpack/hot/dev-server ./src/main.js
08-03
PS D:\My JAVA\苍穹外卖\前端源码\苍穹外卖前端源码\project-sky-admin-vue-ts> npm list vue vue-typescript-admin-template@0.1.0 D:\My JAVA\苍穹外卖\前端源码\苍穹外卖前端源码\project-sky-admin-vue-ts └── (empty) PS D:\My JAVA\苍穹外卖\前端源码\苍穹外卖前端源码\project-sky-admin-vue-ts> npm list vue-area-linkage vue-typescript-admin-template@0.1.0 D:\My JAVA\苍穹外卖\前端源码\苍穹外卖前端源码\project-sky-admin-vue-ts └── (empty) { "name": "vue-typescript-admin-template", "version": "0.1.0", "private": true, "author": "Chong Guo <armourcy@gmail.com>", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "build:uat": "vue-cli-service build --mode production.uat", "lint": "vue-cli-service lint", "svg": "vsvg -s ./src/icons/svg -t ./src/icons/components --ext ts --es6", "test:e2e": "vue-cli-service test:e2e", "test:unit": "vue-cli-service test:unit" }, "dependencies": { "@types/echarts": "^4.4.6", "@types/webpack": "^4.41.12", "area-data": "^5.0.6", "axios": "^0.19.0", "echarts": "^5.3.2", "element-ui": "^2.12.0", "js-cookie": "^2.2.1", "md5": "^2.3.0", "moment": "^2.24.0", "normalize.css": "^8.0.1", "nprogress": "^0.2.0", "path-to-regexp": "^3.0.0", "register-service-worker": "^1.6.2", "vue": "^2.6.10", "vue-area-linkage": "^5.1.0", "vue-class-component": "^7.1.0", "vue-property-decorator": "^8.2.2", "vue-router": "^3.1.2", "vue-svgicon": "^3.2.6", "vuex": "^3.1.1", "vuex-class": "^0.3.2", "vuex-module-decorators": "^0.10.1", "vuex-persistedstate": "^2.7.0" }, "devDependencies": { "@types/jest": "^24.0.18", "@types/js-cookie": "^2.2.2", "@types/nprogress": "^0.2.0", "@types/webpack-env": "^1.14.0", "@vue/cli-plugin-babel": "^3.11.0", "@vue/cli-plugin-e2e-cypress": "^3.11.0", "@vue/cli-plugin-eslint": "^3.11.0", "@vue/cli-plugin-pwa": "^3.11.0", "@vue/cli-plugin-typescript": "^3.11.0", "@vue/cli-plugin-unit-jest": "^3.11.0", "@vue/cli-service": "^3.11.0", "@vue/eslint-config-standard": "^4.0.0", "@vue/eslint-config-typescript": "^4.0.0", "@vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.3", "eslint": "^6.2.2", "eslint-plugin-vue": "^5.2.3", "fibers": "^4.0.2", "jest": "^24.9.0", "sass": "^1.22.10", "sass-loader": "^7.3.1", "style-resources-loader": "^1.2.1", "ts-jest": "^24.0.2", "typescript": "3.6.2", "vue-cli-plugin-element": "^1.0.1", "vue-cli-plugin-style-resources-loader": "^0.1.3", "vue-template-compiler": "^2.6.10", "webpack": "^4.39.3" } }
07-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值