vue-cli 之 jest、@vue/test-utils 单元测试实践

2023-11-03

安装 vue 项目

  • 安装脚手架
npm install -g @vue/cli
  • 创建项目
vue create vue-demo

安装步骤

用例1:renders 组件

// HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

// helloWorld.spec.js
import { createLocalVue, mount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders helloworld', () => {
    const msg = 'new message'
    const wrapper = mount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})

用例2:counter 组件 data 数据

// MyCounter.vue
<template>
  <div class="counter">
    <p>{{count}}</p>
    <el-button @click="addFn">ADD</el-button>
  </div>
</template>

<script>
export default {
  name: 'MyCounter',
  data () {
    return {
      count: 0
    }
  },
  methods: {
    addFn () {
      this.count++
    }
  }
}
</script>

// myCounter.spec.js
import { createLocalVue, mount } from '@vue/test-utils'
import HelloWorld from '@/components/MyCounter.vue'
import { Button } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Button)

describe('MyCounter.vue', () => {
  it('add count', () => {
    const wrapper = mount(HelloWorld, { localVue })
    expect(wrapper.vm.count).toEqual(0)
    const btnClick = wrapper.find('button')
    btnClick.trigger('click')
    expect(wrapper.vm.count).toEqual(1)
  })
})

注意:这里由于 MyCounter.vue 组件,引用了第三方组件库 element-ui 库 button 按钮

import { createLocalVue, mount } from '@vue/test-utils'
import HelloWorld from '@/components/MyCounter.vue'
import { Button } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Button)

const wrapper = mount(HelloWorld, { localVue })

如果没有 createLocalVue 就会报错

console.error
[Vue warn]: Unknown custom element: – did you register the component correctly? For recursive components, make sure to provide the “name” option.

运行结果

  • 输出用例报告配置
// package.json
{
  "jest": {
    "preset": "@vue/cli-plugin-unit-jest",
    "collectCoverage": true,
    "collectCoverageFrom": [
      "src/**/*.{js,vue}"
    ],
    "moduleFileExtensions": [
      "js",
      "jsx",
      "json",
      "vue"
    ]
  }
}

报告集合汇总类型

"coverageReporters": [
  "html",
  "text-summary"
]

实践示例

  • 示例1 【MyInput.vue】
// MyInput.vue
<template>
  <div>
    <el-input v-model="username"></el-input>
    <div
      v-if="error"
      class="error"
    >
      {{ error }}
    </div>
  </div>
</template>

<script>
export default {
  name: 'MyInput',
  data () {
    return {
      username: ''
    }
  },
  computed: {
    error () {
      return this.username.trim().length < 7
        ? 'Please enter a longer username'
        : ''
    }
  }
}
</script>

// myInput.spec.js 风格一
import { shallowMount, createLocalVue } from '@vue/test-utils'
import MyInput from '@/components/MyInput.vue'
import { Input } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Input)

describe('MyInput.vue', () => {
  it('input', async () => {
    const wrapper = shallowMount(MyInput, { localVue })
    await wrapper.setData({ username: ' '.repeat(7) })
    // exists 断言 Wrapper 或 WrapperArray 是否存在
    expect(wrapper.find('.error').exists()).toBe(true)
    await wrapper.setData({ username: 'www.ifrontend.net' })
    expect(wrapper.find('.error').exists()).toBe(false)
  })
})

// myInput.spec.js 风格二
import { shallowMount, createLocalVue } from '@vue/test-utils'
import MyInput from '@/components/MyInput.vue'
import { Input } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Input)

const factory = (values = {}) => {
  return shallowMount(MyInput, {
    localVue,
    data() {
      return {
        ...values
      }
    }
  })
}

describe('MyInput.vue', () => {
  it('初始化', () => {
    const wrapper = factory()
    expect(wrapper.find('input').exists()).toBeFalsy()
  })
  it('输入7个空格', () => {
    const wrapper = factory({ username: ' '.repeat(7) })
    expect(wrapper.find('.error').exists()).toBeTruthy()
  })
  it('输入多余7位数的字符串', () => {
    const wrapper = factory({ username: 'www.ifrontend.net' })
    expect(wrapper.find('.error').exists()).toBeFalsy()
  })
})

  • 示例2 【MyCounter.vue】

测试辅助工具 sinon

spy生成一个间谍函数,它会记录下函数调用的参数,返回值,this的值,以及抛出的异常。
而spy一般有两种玩法,一种是生成一个新的匿名间谍函数,另外一种是对原有的函数进行封装并进行监听。

// MyCounter.vue
<template>
  <div class="counter">
    <p>{{count}}</p>
    <el-button @click="addFn">ADD</el-button>
  </div>
</template>

<script>
export default {
  name: 'MyCounter',
  data () {
    return {
      count: 0
    }
  },
  methods: {
    addFn () {
      this.count++
      this.$emit('change', this.count)
    }
  }
}
</script>

// myCounter.spec.js
import { createLocalVue, mount } from '@vue/test-utils'
import MyCounter from '@/components/MyCounter.vue'
import sinon from 'sinon'
import { Button } from 'element-ui'
const localVue = createLocalVue()
localVue.use(Button)

describe('MyCounter.vue', () => {
  const change = sinon.spy()
  const wrapper = mount(MyCounter, {
    localVue,
    listeners: {
      change
    }
  });
  it('渲染MyCounter组件', () => {
    expect(wrapper.html()).toMatchSnapshot()
  })
  it('add函数', () => {
    const button = wrapper.find('button')
    button.trigger('click')
    expect(wrapper.vm.count).toBe(1)
    expect(change.called).toBe(true)
    button.trigger('click')
    expect(change.callCount).toBe(2)
  })
})
  • 示例3 【MyChild.vue】 provide inject
// MyChild.vue
<template>
  <div class="my-child">
    MyChild:{{test}}
  </div>
</template>

<script>

export default {
  name: 'MyChild',
  inject: ['test']
}
</script>

// myChild.spec.js
import { shallowMount, config } from '@vue/test-utils'
import MyChild from '@/components/MyChild.vue'
config.provide.test = 'test provide value'

describe('MyChild.vue', () => {
  it('初始化', () => {
    const wrapper = shallowMount(MyChild)
    expect(wrapper.find('.my-child').text()).toContain('MyChild:test provide value')
  })
})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue-cli 之 jest、@vue/test-utils 单元测试实践 的相关文章

  • JavaScript 中的埃拉托斯特尼筛法对大量数据无限运行

    我一直在尝试写埃拉托斯特尼筛法 http en wikipedia org wiki Sieve of EratosthenesJavaScript 中的算法 基本上我只是按照以下步骤操作 创建从 2 到 n 1 的连续整数列表 令第一个素
  • Javascript Promise“then”始终运行,即使 Promise 未能执行

    我希望当调用第二个 then 时不执行第三个 then 但是 即使 Promise 被拒绝 调用第二个 then 并且代码返回 rejected 然后返回 undefined 它仍然调用第三个 then 如何不运行第三个 then 这样 未
  • Chrome 中的性能问题

    我目前正在从事一个相对较大的项目 使用 AngularJs 构建 应用程序的一部分是一个表单 您可以向其中添加任意数量的页面 不幸的是 添加了很多不必要的垃圾 即表示表单模型的对象可能会变得非常大 在某些时候 Chrome 基本上无法处理它
  • 图像无法在带有 DOM 的 IE 中加载:控制台中的 7009 错误(无法解码)

    当在 IE 中的单个页面上加载许多图像时 在 IE11 中重现 其中一些图像开始加载失败 并在控制台中出现类似以下警告的内容 DOM7009 无法解码 URL 处的图像 某些唯一的 url 当我查看网络流量时 似乎确实从服务器收到了每个图像
  • 引导程序提前输入未填充承诺的响应

    我的引导程序预输入如下
  • 隐藏 Div 的父级

    我只是想隐藏父divcomments section div class content content green div div div 我试过这个 document getElementById comments section pa
  • Bootstrap按钮加载+Ajax

    我正在使用 Twitter Bootstrap 的按钮加载状态 http twitter github com bootstrap javascript html buttons http twitter github com bootst
  • 设置 cookie 时中断 JavaScript 执行

    当设置 cookie 时 是否可以始终中断浏览器开发人员工具中的 javascript 执行 无需显式设置 JS 断点 document cookie 在 html head 块的开头添加此代码片段效果很好
  • 在 HTML5 画布中,如何用我选择的背景遮盖图像?

    我试图用画布来实现这一点 globalCompositeOperation 但没有运气 所以我在这里问 这里有类似的问题 但我没有在其中找到我的案例 我的画布区域中有图层 从下到上的绘制顺序 画布底座填充纯白色 fff 用fillRect
  • 检查 jQuery 1.7 中是否存在基于文本的选择选项

    所以我有以下 HTML 片段
  • window.location 和 location.href 之间的区别

    我对之间的区别感到困惑window location and location href 两者似乎都以相同的方式行事 有什么不同 window location是一个对象 它保存有关当前文档位置的所有信息 主机 href 端口 协议等 lo
  • 刷新页面时保存用户的选择

    我目前有一个页面显示不同团队的数据 我有一些数据 用户可以单击使其处于 打开 或 关闭 状态 并为每个数据显示不同的图标 它基本上就像一个清单 只是没有物理复选框 我想记住哪些 复选框 已被选中 即使在用户刷新页面或关闭浏览器并稍后返回之后
  • 为什么我们在打字稿中使用 HTMLInputElement ?

    我们为什么使用 document getElementById ipv as HTMLInputElement value 代替 document getElementById ipv value 功能getElementById返回具有类
  • 从数据库检查数据的异步解决方案各种循环子句

    我想要做的是异步检查数据库并从中获取结果 在我的应用程序中我试图实现Asynchronously将此步骤解决为 从数据库中检查手机号码JsonArray循环子句的种类 Create JsonArray从结果 打印创建的数组 我学到了足够多的
  • 对于只触及我的工作表的 Google 表格脚本,收到“此应用程序未经验证”

    我正在编写一个 Google Sheets 脚本 我只想访问与 gs 文件关联的同一电子表格中的数据 似乎我应该有权在自己的电子表格中运行脚本 但是每当我运行一个函数时 我都会得到一个This app isn t verified信息 我该
  • 在 JavaScript 循环之外声明变量可以提高速度和内存?

    C 也有类似的问题 但我们没有看到 JavaScript 的任何问题 在循环内声明变量是否可以接受 假设循环有 200 次迭代 使用样本 2 相对于样本 1 是否有性能要求 内存和速度 我们使用 jQuery 来循环 它提高了我们将 var
  • 从 FileReader 设置背景图像样式

    我正在寻找一种解决方案 允许我从文件上传输入中获取文件并通过设置 document body style backgroundImage 来预览它 以下代码用于在 Image 元素中显示预览 function setImage id tar
  • 分页在服务器端好还是前端好? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在构建 Laravel Vue 应用程序 我想知道在后端使用分页还是在前端使用分页更好 我认为最好在每页发送尽可能少的数据的请求 但我想听听
  • 如何在执行新操作时取消先前操作的执行?

    我有一个动作创建器 它会进行昂贵的计算 并在每次用户输入内容时调度一个动作 基本上是实时更新 但是 如果用户输入多个内容 我不希望之前昂贵的计算完全运行 理想情况下 我希望能够取消执行先前的计算并只执行当前的计算 没有内置功能可以取消Pro
  • 如何使用asm.js进行测试和开发?

    最近我读到asm js规范 看起来很酷 但是是否有任何环境 工具来开发和测试这个工具 这还只是处于规范阶段吗 您可以尝试使用 emscripten 和 ASM JS 1 并从侧分支在 firefox 构建中运行它 有关 asm js 的链接

随机推荐

  • 沉浮于各种文件型数据库 hsqldb h2 还是derby

    原始发表时间 2009 09 10 经过几天的折腾终于还是心碎了 前前后后为了这个数据库共计花费了约2周的时间 系统采用的是经典技术框架 Spring 2 0 5 Hibernate 3 2 iBatis 2 2 0 用于连接文件型数据库的
  • CI/CD持续集成之git命令

    持续集成主要步骤 持续集成的定义 互联网开发已经形成一套标准的流程 最重要的组成部分就是持续集成 持续集成的好处就是 频繁将代码集成到主干 它的优点 1快速发现错误 2 防止分支大幅度偏离主干 意义 就是让产品进行持续迭代 同时保持高质量交
  • git学习1之基本原理

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Git 基础 那么 简单地说 Git 究竟是怎样的一个系统呢 请注意接下来的内容非常重要 若你理解了 Git 的思想和基本工作原理 用起来就会知其所以然 游刃有余 在开始学
  • R手册(Visualise)--ggplot2

    文章目录 Overview Geoms 基本图形 单变量 双变量 三变量 文本 误差可视化 地图 Stats Scales 常用标尺格式 坐标轴标尺 Color and fill scales Shape and size scales C
  • mysql使用参数

    调优 Show status 动态查看mysql状态 top 同理 Show variables 静态查看 Show processlist 查看运行任务列表 Show status like Com 查看系统参数 Show global
  • 新开ubuntu的必要优化

    博主不是专业的运维人员 有时候新开业务服务器到生产环境忘记配置ubuntu的配置时候 就发生各种奇怪的悲剧比如 redis出现大量TIMEWAIT状态 并且服务器不会收 原因是tcp tw recycle配置为0等等 为避免遗忘记录下新开的
  • 国内可用的css,js,图标字体,等常用前端公共库CDN服务

    CDN的全称是Content Delivery Network 即内容分发网络 其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节 使内容传输的更快 更稳定 通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的
  • 参数校验Jakarta Bean Validation学习

    不断学习更新中 同教程代码 码云 1 背景 我们在平时的学习与工作中 都需要对参数进行校验 比如在注册时 用户名密码不能为空 用户名长度必须小于10等等 虽然有些校验在前端页面会进行验证 但是后端为了增加健壮性也需要对这些参数进行判断 比如
  • mqtt报文逐条解析

    文章目录 1 背景说明 2 mqtt报文解析 3 剩余长度计算 4 构建connect报文 5 CONNACK报文示例 6 心跳PING报文 7 心跳回应PINGRESP报文 8 断开连接DISCONNECT报文 9 订阅请求SUBSCRI
  • unity 3D RPG教程(四)

    目录 声明 16 AttackData 攻击属性 17 Execute Attack 实现攻击数值计算 18 Guard Dead 守卫状态和死亡状态 19 泛型单例模式 Singleton 20 Observer Pattern 接口实现
  • Mac OS X 10.9 配置jdk1.7

    首先 我们下载个eclipse 或者任何java运行程序 双击 Mac OS会提示你安装jre运行时环境 按照提示安装就可以了 Mac OS 10 9会安装jdk1 6 苹果提供的Java都安装在 System Library Framew
  • linux - 配置Ramdisk创建内存盘 (**)

    在任何Linux发行版中创建RAM磁盘 linux 配置Ramdisk创建内存盘 在任何Linux发行版中创建RAM磁盘 1 什么是内存磁盘 RAM磁盘也称为RAM驱动器 它是使用文件系统格式化的 RAM 的一部分 您可以将其挂载到 Lin
  • 2D平面中关于矩阵(Matrix)跟图形变换的讲解

    原文 http blog csdn net linmiansheng article details 18801947 在二维平面上 常用的有以下三种基本的图形变化 1 Translation 2 Scale 3 Rotation 在And
  • git如何把一个分支的commit提交到另一个分支上

    项目版本管理使用git 在实际工作当中经常会遇到计划赶不上变化 比如某几个改动要提前上线 或者某几个改动这次不发布 如果是时间间隔短 改动量小以及个人记忆强大的基础上没什么事 弄个个新分支把需要的弄出来 或者屏蔽掉 但是如果上面三个条件有一
  • 基于麻雀算法优化广义神经网络GRNN的数据分类预测,SSA-GRNN分类预测,多特征输入单输出的二分类及多分类模型,MATLAB2018以上。多特征输入单输出的二分类及多分类模型。程序内注释详细,

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 读取数据 res xlsread 数据集 xlsx 分析数据 num class length unique
  • python flask框架下登录注册界面_Flask框架通过Flask_login实现用户登录功能示例

    form hidden tag form username class form control input lg placeholder 用户名 form password class form control input lg plac
  • linux下miniconda卸载

    conda是一个开源的包 环境管理器 可以用于在同一个机器上安装不同Python版本的软件包及其依赖 并能够在不同的Python环境之间切换 Anaconda包括Conda Python以及一大堆安装好的工具包 比如 numpy panda
  • 英国几个有名的英语考试总结

    2023年3月23日 英国资格考试监管机构 Ofqual 发布年度报告 对各类考试进行了总结 其中就有关于英语考试 ESOL English for Speakers of Other Languages 类的总结 网络上很多人对 ESOL
  • 【Linux】如何将ntfs硬盘挂载到home目录下并具有读写权限

    步骤 1 查看当前挂载的硬盘及其挂载点 2 查看需要挂载到home下的磁盘类型信息 3 在home下新建一个空的文件夹作为该磁盘的新挂载点 4 以ntfs类型的硬盘为例 使用mount命令进行挂载 5 问题1 进程占用了磁盘 6 问题2 磁
  • vue-cli 之 jest、@vue/test-utils 单元测试实践

    安装 vue 项目 安装脚手架 npm install g vue cli 创建项目 vue create vue demo 安装步骤 用例1 renders 组件 HelloWorld vue