vue 单元测试

前言:网上一大堆的单元测试,但是很少针对vue的单元测试,不过也有一些视频简单的讲解了,这里为了方便各位前端朋友快速上手,简单过一遍 单元测试

这里不举例我自己的页面,怕大家看不懂,以下代码片段,有部分会来自网上

1. 创建页面

在根目录下找到 tests文件夹在iview文件下创建以实际测试文件路径相仿的文件

比如我在 src/iview/Home 下 有一个 Home.vue

那么我们的 单元测试文件就要

tests/iview/Home/Home.spec.js

vue 单元测试_第1张图片

如果外面那个 Home.vue 要测,那你 一样的文件位置要对应

注意:测试文件要以 被测文件名.spec.js 命名

2. 引入各种文件

引入 @vue/test-utils (这里默认你已经安装好引入 @vue/test-utils 并且配置好)

import { mount, flushPromises } from '@vue/test-utils'

引入组件(必要)

无论是 子组件,自定义组件,框架内的组件,自身文件,都要一一引入

import Home from '@/views/Home/Home.vue'            // 自身
import HomeTable from '@/components/HomeTable.vue'  // 子组件

以element为例引入组件

import { ElMessageBox, ElTableColumn, ElTable } from 'element-plus'

引入接口(有需要才引入,这里只是扩展)

import { tableList } from '@/api/index'

引入插件 (有需要才引入,这里只是扩展)

以 lodash-es.js 举例
lodash-es.js 是一个处理 各种形式类型数据的一个插件,比如我们深拷贝一个对象,传统 js 处理就是 JSON.parse(JSON.stringify(…)) 在我们项目中是不推荐的,所以利用 lodash-es.js 处理,详情可以看我之前的文章

import { cloneDeep } from 'lodash-es'

引入路由 (有需要才引入,这里只是扩展)

import { useRouter } from 'vue-router'

引入Vuex (有需要才引入,这里只是扩展)

import { createStore } from 'vuex'

3. 调用各种引入的文件

把组件相关全部调用

const componentGlobal = {
  components: {
    'home-table': HomeTable,  // 组件
    ElMessageBox,             // element的组件(框架组件)
    ElTableColumn, 
    ElTable
  }
}

编写接口返回(假)数据

const mockListData = {
  "phone": "1354490525",
  "isVip": 0,
  "createTime": "2021-12-06 00:00:00",
  "name": "测试人员1",
  "id": "h5214so514w1206",
  ...
}

const mockResponse = {
  data: {
    "msg": "success",
    "code": 200,
    "page": {
      "totalCount": 1,
      "pageSize": 10,
      "totalPage": 1,
      "currPage": 1,
      "list": [
        mockListData
      ]
    }
  }
}

mock 接口

将上面的数据当作返回数据

jest.mock('@/api/index', () => ({
  tableList: jest.fn(() => Promise.resolve(mockResponse)),
}))

mock 对话框/路由 (部分组件时找不到节点的,需要mock)

// mock 路由
jest.mock('vue-router', () => ({
  useRouter: jest.fn(() => ({
    push: () => ({})
  }))
}))
// mock 对话框 (他是通过 ElMessageBox. 弄出来,并没有把节点写在页面上,所以需要mock)
jest.mock('element-plus', () => ({
  ...jest.requireActual('element-plus'),
  ElMessageBox: {
    confirm: jest.fn(),
    cancel: jest.fn(),
  }
}))

有用到 Vuex 需定义 store

const store = createStore({
  modules: {
    user: {
      namespaced: true,
      state: {
        userId: "07cbccc0039"
      },
    },
  }
})

4. 开始测试

挂载

describe('测试 Home 页面是否正常工作', () => {     // 中文部分按自己的来,在只用来展示
  const mockScrollTo = jest.fn()
  let wrapper: VueWrapper<ComponentPublicInstance<any>>
  beforeEach(() => {
    wrapper = mount(Home, {
      global: {
        ...componentGlobal,
        provide: {
          scrollTo : mockScrollTo,
          store                                  /// 用到 Vuex 的可以加上
        },
      }
    })
  })
})

如果时测组件,还要把props的值加上

describe('测试 HomeTable 组件是否正常工作', () => {
  let wrapper: VueWrapper<ComponentPublicInstance<any>>
  beforeEach(() => {
    wrapper = mount(HomeTable, {
      props: {
	      dataList: cloneDeep(mockListData),  // cloneDeep是深拷贝
    },
      global: {
        components,
      },
    })
  })
 })

在这包裹下我们可以把我们要测试的东西全部通过

it('测试内容', ()=>{})

测试展示

利用

wrapper.findAll()
wrapper.find()
wrapper.findComponent()
wrapper.findAllComponents()

这些 api 来校验页面是否预期展示需要的组件

测试点击

一样先找到要点击按钮的节点,通过 trigger(‘click’) 模拟点击

it('测试点击', async () => {
	wrapper.find('.add').trigger('click')     // 找到节点,模拟点击
})

如果节点较多,则需要找其中一个进行测试

it('测试点击', async () => {
	const ElTableColumnComponent = wrapper.find('.tableList')           // 找到节点
	ElTableColumnComponent.findAll('.updateBtn')[0].trigger('click')    // 模拟点击
})

测试接口

如果点击后他要执行某些操作,如跑接口

it('测试接口', async () => {
	ElTableColumnComponent.findAll('.deleteBtn')[0].trigger('click')
	
	// deleteUser 指接口名
	// mockImplementationOnce 官方api 指调用一次
	// delMockResponse 返回数据
	
	const delMockResponse = {
	  "msg": "success",
	  "code": 200
	};  // 注意这个; 
	(deleteUser as jest.Mock<any>).mockImplementationOnce(() => Promise.resolve(delMockResponse))   // 模拟接口
})

一般测试只测他流程能不能走通

测试组件返回信息

我们有时候会用到子组件,子组件会 emit 回一个方法和参数

例如

<home-table
   :data-list="tableList"
    @changeDate="changeDateHandle"
 />
it('测试子组件返回', async () => {
	const data = {
		"id": "cs24545132hs5"
	}
	const HomeTableComponent = wrapper.findComponent(HomeTable)  // 找到这个组件节点
	HomeTableComponent.vm.$emit('changeDate', data)   // newMockListData 返回数据
})

测试跳转

  it('测试页面跳转是否正常', async () => {
    const push = jest.fn()
    useRouter.mockImplementationOnce(() => ({ push }))
    // mock 完毕需要重新挂载
    const wrapper = mount(MyPatientList, {
      global: {
        ...componentGlobal,
        provide: {
          scrollTo: mockScrollTo
        }
      }
    })
  })

watch 测试

watch是监听,所以我们直接给监听的值赋一个新的值就可以了

wrapper.vm.要赋值的对象 = 新的值

5. 进阶

测试页面写完 请运行命令

npm run ut:coverage

可以在项目内 coverage\lcov-report 找到一个 index.html 页面,点击既可以查看该项目测试覆盖率

一般 绿色就代表单元测试通过,当然覆盖率越高越好

在这里插入图片描述
点击到自己测试的文件

文件内红色的代码没测到

多看文档 文档虽然不是很清晰,但是基本上的方法还是够用的

官方文档

多写多练

6. 常用命令

请浏览我这篇文章

你可能感兴趣的:(jest,单元测试,前端,-,学习,vue.js,单元测试,前端)