vue 中的单元测试

一、背景

随着项目越来越大,复杂度上升,改动一个地方,可能造成连环反应,引发未知 bug

我们需要在保证项目稳定的情况下,进行开发

这里选择 jest 作为测试框架

配置少,功能完善

二、安装与配置

1、安装 jest、@vue/test-utils

jest: 测试框架
@vue/test-utils: vue 测试工具,用来提供包裹 vue 组件,并暴露一些用来操作组件的方法和属性
yarn add jest @vue/test-utils -D

2、在 package.json 中添加 script 命令

{
    "script": {
        "test": "jest" // 在 node 环境中运行 jest 命令
    }
}

3、安装 vue-jest 处理 vue 文件

yarn add vue-jest -D

添加 jest 配置文件 jest.config.js

// webpack 是支持 ES modules的,所以默认不开启 ES modules 转译
// 这里要设置开启 ES modules 转译,因为 node 环境不一定支持新特性
process.env.VUE_CLI_BABEL_TARGET_NODE = true
process.env.VUE_CLI_BABEL_TRANSPILE_MODULES = true

module.exports = {
  // 告诉 jest 处理 js、jsx、json、vue 文件
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],

  // 告诉 jest 使用 vue-jest 处理 vue 文件
  transform: {
    '.*\.(vue)$': 'vue-jest'
  },

  // jest 默认忽略对 node_modules 的转换解析,我们项目中有使用到 vant 等包,所以不能忽略
  // 这里随便写一个资源路径进行覆盖
  transformIgnorePatterns: ['/src/assets'],

  // 告诉 jest 关于 webpack 中的别名解析
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1' // 对应 @ ---> src
  },

  // snapshotSerializers: ['jest-serializer-vue'],

  // 启动测试命令时,自动寻找匹配文件执行
  testMatch: [
    '**/test/**/*.test.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
  ]

  // testURL: 'http://localhost/',

  // watchPlugins: [
  //     'jest-watch-typeahead/filename',
  //     'jest-watch-typeahead/testname'
  // ]
}

4、安装 babel-jest

测试代码可能使用了很多新的语法特性

因为是跑在 node 环境中,node 可能并不支持

所以要使用 babel-jest 在运行代码前来进行转换

yarn add babel-jest -D

在 jest.config.js 中 transform 属性添加配置

module.exports = {
  // 告诉 jest 使用 babel-jest 处理 js 文件
  transform: {
    '^.+\.js$': 'babel-jest'
  }
}

5、安装 jest-transform-stub

解析到静态资源如图片、样式表时使用 jest-transform-stub 处理

jest-transform-stub 实际是返回一个空字符串,因为测试时并不需要这些资源

yarn add jest-transform-stub -D

在 jest.config.js 中 transform 属性添加配置

module.exports = {
  // 告诉 jest 使用 jest-transform-stub 处理静态资源
  transform: {
    '.+\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub'
  }
}

6、放置测试文件

默认情况下 jest 会递归查找整个项目中所有的 .spec.js 和 .test.js 扩展名的文件

推荐在测试目录下创建一个 __test__ 目录,放置测试文件

7、eslintrc.js

在 env 中加入 jest,让 eslint 识别 jest 全局变量

{
  env: {
    jest: true
  }
}

三、使用

思考测试逻辑

    // 一开始不知道要测试什么,怎么测试
    // 我们可以把需要测试的情况罗列出来,然后一一编码,先思考后动手
    // 1、issuerName           1、截取18个字符 2、没有值时为'--'
    // 2、h2Style              1、发行人+标签长度如果大于22,则改变字体大小
    // 3、limitTags            1、最多截取三个标签 2、没有值时为[]
    // 4、buyYtm               1、精确到小数后3位 2、没有值时为'--'
    // 5、paymentFrequency     1、有值时后续加上'付息' 2、没有值时位'--'
    // 6、paymentDates         1、付息日超过2个(不包含)则在后面加上'等',并且只截取前两个展示 2、没有值时为'--'

取值对比方式

    // Q:直接使用 wrapper.vm 获取数据进行对比还是取页面上展示的文本进行对比?
    // A:我比较倾向于第二种,取页面上展示的文本进行对比
    // 组件中可能因为各种原因,不敢修改之前的变量数据。
    // 此时新增变量替换原先模板中的变量,页面上展示改变了,但是脚本中原有变量还在,测试正常通过,这是不对的
    // 所以应该以实际页面展示为准。
    // 只有在页面上无法测试到的时候,直接拿 wrapper.vm 上的数据对比

方法

1、构造输入值
2、传入`构造输入值`给要测试的方法, 并执行
3、对比测试执行方法`返回的结果/产生的影响`与预期的是否一样

util 测试

如果引入了依赖包,jest 找不到,需要在 jest.config.js 中的 moduleNameMapper 配置依赖包的解析路径

moduleNameMapper: {
    '^dayjs$': '<rootDir>/node_modules/dayjs'
}

window.location.href 需要在 jest.config.js 中的

testURL: 'http://www.baidu.com?test1=123&test2=321'

自定义日期对象方法,可以测试倒计时类似的方法

let t1 = new Date('2020-05-15').getTime()
let t2 = new Date('2022-05-15').getTime()
let initTime = new Date('2019-10-18').getTime()
Date.prototype.getTime = function() {
    return initTime
}

props 测试

const wrapper = mount(component, {
    propsData: {

    }
})
wrapper.props()
wrapper.props('key')

以下待补充~~~~

state 测试

mutation 测试

action 测试

API 调用测试

mock 数据走完流程

都读到最后了、留下个建议如何
原文地址:https://www.cnblogs.com/linjunfu/p/14651875.html