继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【九月打卡】第1天 使用 vue-test-utils 测试组件

flask
关注TA
已关注
手记 45
粉丝 2
获赞 1

课程名称:web前端架构师

课程章节:第11周 第三章

主讲老师:张轩

课程内容:掌握测试基本工具,给组件库添加单元测试

课程收获和心得

课程中使用了 webpack + jest + vue-test-utils 为组件添加测试,由于 vite 的打包速度比webpack快了几十倍,所以我根据我在这里使用了vitest代替 jest,vite 代替webpack。会使用 jest 基本上可以直接使用 vitest

环境准备

安装依赖

pnpm i vitest vue-test-utils jsdom @vitest/coverage-c8 -D

在 package.json 文件中增加启动命令

"scripts": {
    "test": "vitest",
    "test:run": "vitest run --coverage"
 }

要测试 vue组件,需要在 vite.config.ts 文件中配置 vitest。如下面所示,environment 用来设置环境,默认时node 环境,web 浏览器环境可以使用 jsdom 或 happy-dom(https://cn.vitest.dev/config/#environment); coverage.provider 用来设置覆盖工具(https://cn.vitest.dev/guide/coverage.htm)

+ /// <reference types="vitest" />
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      '@': path.join(__dirname, 'src')
    }
  },
  plugins: [
    vue(),
    eslintPlugin()
  ],
+  test: {
+   environment: 'jsdom',
+     coverage: {
+     provider: 'c8' 
+    }
  }
})

测试渲染和元素获取

<script setup lang="ts">
defineProps<{msg: string}>()
</script>
<template>
  <h1>{{ msg }}</h1>
</template>

测试代码

describe('HelloWorld.vue', () => {
  const msg = 'Vue + Ts + Vitest'
  const wrapper = shallowMount(HelloWorld, {
    props: {
      msg
    }
  })
  it('render props message when passed', () => {
    expect(wrapper.get('h1').text()).toBe('Vue + Ts + Vitest')
  })
 }

wrapper.get 和 wrapper.find 都可以用来获取元素。使用 get 时没有找到匹配元素时就会中断报错

测试代码

import { shallowMount } from '@vue/test-utils'

describe('HelloWorld.vue', () => {
  const msg = 'Vue + Ts + Vitest'
  // 也可以使用 mount
  const wrapper = shallowMount(HelloWorld, {
    props: {
      msg
    }
  })
  it('render props message when passed', () => {
    expect(wrapper.get('h1').text()).toBe('Vue + Ts + Vitest')
  })
 }

查找组件,可以使用wrapper.findComponent 或 wrapper.getComponent

import HelloWorld from '@/components/HelloWorld.vue'
describe('App.vue', () => {
  it('mount HelloWorld', () => {
    expect(wrapper.getComponent(HelloWorld))
  })
}

触发事件

使用 trigger 用来触发事件

  it('test click', async () => {
    await wrapper.get('button').trigger('click')
    console.log(wrapper.get('.card').text())
    expect(wrapper.get('.card').text()).toBe('count is 1')
  })

更新表单

可以使用 setValue 设置输入值

  it('test input', async () => {
    const textInput = wrapper.find('input[type="text"]')
    const inputVal = 'todos'
    await textInput.setValue(inputVal)
    expect(textInput.element.value).toBe(inputVal)
  }

验证事件是否发送

wrapper.emmit

  it('test emmit', async () => {
    ...
    // 当按下 enter 键时,向父组件发送事件 commit
    await textInput.trigger('keyup.enter')
    expect(wrapper.emitted()).toHaveProperty('commit')
    const events = wrapper.emitted('commit')
    expect(events[0]).toEqual([inputVal])
  })

测试异步请求

模板代码

<script setup lang="ts">
import axios from 'axios'
import { ref } from 'vue'
  interface User{
    id: number
    name: string
    email: string
    phone: string
 }
const user = ref<User | null>(null)
const loadError = ref(false)
const loading = ref(false)
function loadData () {
  loading.value = true
  loadError.value = false
  axios.get<User>('https://jsonplaceholder.typicode.com/users/1').then(res => {
    user.value = res.data
  }).catch(e => {
    loadError.value = true
  }).finally(() => {
    loading.value = false
  })
}
loadData()
</script>
<template>
  <div
    v-if="loading"
    class="loading"
  >
    加载中
  </div>
  <div v-else>
    <div class="username">
      姓名:{{ user.name }}
    </div>
    <div class="phone">
      电话:{{ user?.phone }}
    </div>
    <div class="email">
      邮箱:{{ user?.email }}
    </div>
  </div>
  <div
    v-if="loadError"
    class="err"
  >
    加载出错
  </div>
  <button
    @click="loadData"
  >
    重新加载
  </button>
</template>

测试代码

vi.mock('axios')

describe('Async App.vue', () => {
  it.only('test async request', async () => {
    axios.get.mockResolvedValue({ data: { id: 2, name: 'shibin', email: 'shibin.xx@xx.com', phone: '11111111111' } })
    const wrapper = shallowMount(App)
    expect(axios.get).toHaveBeenCalled()
    expect(axios.get).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users/1')

    expect(wrapper.find('.loading').exists()).toBeTruthy()

    // 所有异步数据加载完毕
    await flushPromises()
    
    expect(wrapper.find('.loading').exists()).toBeFalsy()
    expect(wrapper.find('.err').exists()).toBeFalsy()
    expect(wrapper.get('.username').text()).toBe('姓名:shibin')
    expect(wrapper.get('.phone').text()).toBe('电话:11111111111')
    expect(wrapper.get('.email').text()).toBe('邮箱:shibin.xx@xx.com')
  })
})

写测试代码没有什么难度,多看看文档就可以了

相关文档链接

图片描述

图片描述

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP