Vue 项目添加单元测试发现的问题及解决

摘要:
用Jest测试单文件组件1、安装Jest和VueTestUtilsnpminstall--save-devjest@vue/test-utils2、配置package.json//package.json{"scripts":{"test":"jest"}}3、需要安装和配置vue-jest预处理器npminstall--save-devvue-jest4、在package.json中创建一个je
用 Jest 测试单文件组件

1、安装 Jest 和 Vue Test Utils

npm install --save-dev jest @vue/test-utils

2、配置 package.json

// package.json
{
  "scripts": {
    "test": "jest"
  }
}

3、需要安装和配置 vue-jest 预处理器

npm install --save-dev vue-jest

4、在package.json 中创建一个 jest 块或在项目根目录创建 jest.config.js

module.exports = {
  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
  transform: {
    '^.+\.vue$': 'vue-jest',
    '.+\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
     // 为 Jest 配置 Babel
    '^.+\.jsx?$': 'babel-jest'
  },
  transformIgnorePatterns: ['/node_modules/'],
  // 别名
  moduleNameMapper: {
    '^@/(.*)$': '<rootdir>/src/$1'
  },
  snapshotSerializers: ['jest-serializer-vue'],
  testMatch: [
    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
  ],
  testURL: 'http://localhost/',
  watchPlugins: [
    'jest-watch-typeahead/filename',
    'jest-watch-typeahead/testname'
  ]
};

错误信息处理

1、babel 解析 es6 出错,需要配置 babel 预设
Vue 项目添加单元测试发现的问题及解决第1张
Vue 项目添加单元测试发现的问题及解决第2张
> 需要配置安装 @babel/preset-env [babel-preset-env 会有问题]

npm install --save-dev @babel/preset-env

> 配置 babel.config.js

module.exports = {
  presets: [
    // 使可以正常运行 vue 项目,
    '@vue/app',
    [
      '@babel/preset-env',
      {
        modules: false,
      }
    ]
  ],
  env: {
    test: {
      presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
    }
  }
}

2、npm test
Vue 项目添加单元测试发现的问题及解决第3张
> 清除缓存,然后再执行测试参考链接

最后问题还是很多,比如 UI 包的引用,webpack require.context 的问题等

然后就决定重新创建一个项目,看看有没有问题(想着官网的例子不应该是有问题的)

1、创建项目

vue create jest-demo

2、选择插件包(前一个项目大致的插件【vue-router, vuex, dart-sass, babel, eslint, unit-jest】)安装

vue-router, vuex, dart-sass, babel, eslint, unit-jest

3、写一个简单的组件('@/components/HelloWorld.vue')用做测试,简单含有一些之前项目会遇到的情况(store【如 mapGetter】、element-ui标签)

<template>
  <div class="hello">
    <div>{{msg}}</div>
    <el-row type="flex" align="middle">
      <el-col :span="4">userName</el-col>
      <el-col :span="8"><el-input v-model="moduleUserName"></el-input></el-col>
    </el-row>
    <el-button type="primary" @click="changeUser">change user</el-button>
  </div>
</template>

<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
  name: 'HelloWorld',
  props: {
    msg: String,
  },
  data() {
    return {
    }
  },
  computed: {
    ...mapGetters(['storeUserName']),
    moduleUserName: {
      set(name) {
        this.updateUserName(name)
      },
      get() {
        return this.storeUserName
      }
    }
  },
  methods: {
    ...mapMutations(['updateUserName']),
    changeUser() {

    },
  }
};
</script>

4、写一个对应的测试文件

import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex'
import ElementUI from 'element-ui';
import HelloWorld from '@/components/HelloWorld.vue';
import store from '@/store'

describe('HelloWorld.vue', () =&gt; {
  it('renders props.msg when passed', () =&gt; {
    const localVue = createLocalVue()
    localVue.use(Vuex)
    localVue.use(ElementUI)
    const msg = 'new message';
    const wrapper = shallowMount(HelloWorld, {
      // 做一个数据的传
      propsData: { msg },
      // 使用 store
      store,
      // 避免混入和安装插件而污染全局 Vue
      localVue,
    });
    expect(wrapper.text()).toMatch(msg);
  });
});

Vue 项目添加单元测试发现的问题及解决第4张
OK 没有问题了,把包的配置和各文件的配置写入老再试试


5、原项目中有自动引入固定前缀的组件的插件,需要用到 webpack 的 require.context 函数对文件做检索,然后 babel-jest 是没有的,所以需要引用一个三方的插件来提供这个功能

  • 安装 babel-plugin-require-context-hook
cnpm install babel-plugin-require-context-hook 
  • 在测试文件夹内创建文件 tests/unit/lib/register-context.js
import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
registerRequireContextHook();
  • 在 jest.config.js 中配置 jest 预配置,使可以使用 require.context
setupFiles: ['<rootdir>/tests/unit/lib/register-context.js']
  • 在 babel.config.js 中配置 test 环境插件 require-context-hook
env: {
    test: {
        plugins: ['require-context-hook']
    }
}

6、其他的一些设置

  • 因为项目中有引用 element-ui 和 vue-awesome,需要被 babel 解析,排除掉这两个包,在 jest.config.js 中配置
transformIgnorePatterns: [
    'node_modules/(?!(element-ui|vue-awesome)/)'
 ],
  • 因为很多测试组件的时候需要引入很多文件或包,所以就提出来 js 文件,类似 vue 的 main.js ,做入口的统一处理,
  • 创建 tests/unit/lib/before-test.js 【基本的都是在 main.js 中引入的或添加】
// 为了方便 单元测试
// eslint-disable-next-line import/extensions
import element from '@/plugins/element'
import baseComponent from '@/plugins/base-component'
import registeSvgIcon from '@/plugins/registe-svg-icon'
import API from '@/request/api'
import axios from '@/request'
import utils from '@/utils'
jest.mock('axios')
export default (Vue) =&gt; {
  element(Vue)
  baseComponent(Vue)
  registeSvgIcon(Vue)
  Vue.prototype.$API = API
  Vue.prototype.axios = axios
  Vue.prototype.$util = utils
}

  • 创建 Hello.vue 组件【@/views/pages/Hello】
<template>
  <div class="hello">hello</div>
</template>

<script>
export default {
  name: 'hello',
  created() {
    console.log('hello')
  }
}
</script>

<style lang="scss" scoped="">
.hello {}
</style>

  • 创建测试文件 tests/unit/hello.spec.js
import { shallowMount, createLocalVue } from '@vue/test-utils'
import './lib/before-test'
import Hello from '@/views/pages/Hello'

describe('我是外层分组', () =&gt; {
  const localVue = createLocalVue()
  const wrapper = shallowMount(Hello, { localVue })
  it('wrapper 是一个 vue 组件实例', () =&gt; {
    expect(wrapper.isVueInstance()).toBeTruthy()
  })
})

Vue 项目添加单元测试发现的问题及解决第5张
7、然后就可以学习 jest ,并用 jest 具体的添加单元测试了【虽然没有按问题来解决,但是项目添加单元测试总算OK了,先学习jest吧,再遇到问题再解决问题,结果是好的就好了~~】


  • 其他的一些问题
    Vue 项目添加单元测试发现的问题及解决第6张
    原因:jsdom不支持canvas,需要额外引入包
    解决:安装jest-canvas-mock包,在jest的配置文件中添加 setupFiles: ['jest-canvas-mock']

免责声明:文章转载自《Vue 项目添加单元测试发现的问题及解决》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇移动端1px解决方案centos网速特别慢的最佳解决的方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

vue指令(7)v-on

理论知识 双向数据绑定中,数据有多个来源,包括后台业务数据,用户网页操作数据等。对于用户网页操作,vue提供了事件机制,对用户操作做出反应。 使用方式 v-on:标准事件='事件处理逻辑'。 标准实践包括点击(click)、焦点(focus)等。在标签中使用时有四种方式,以点击事件为例 < button v-on:click='msg++'>...

vue 文件中的注释

在每个代码块内,注释的时候,需要使用各自语言的注释语法去注释(HTML、CSS、JavaScript、Jade 等)。在文件最顶部注释的时候用HTML的注释语法:<!— 在这里写注释的内容 --> 。 html 注释: <!-- 注释,单行或多行 --> pug(html) 注释:https://pugjs.org/zh-cn...

Vuejs学习笔记(一)

1)    vue.js 的 主要功能 1、模板渲染 2、模块化 3、扩展功能:路由,Ajax 2)    vue.js 模板渲染之双向绑定示例 message 绑定到了 input 对象,所有在input中的值修改了之后,上面的P 标签的显示的内容也会根据其改变。   3)    app.vue 、main.js和 index.html的关联 (1) m...

Vue+koa2开发一款全栈小程序(3.vue入门、Mpvue入门)

1.Vue-cli 1.新建一个vue项目 打开cmd 官方命令行工具 npm install -g vue-cli //安装脚手架 cd到你想要存放demo的目录下,然后 vue init webpack vue-demo //新建demo  其中user EsLint....那一行选项要选n 还有选最后一条时,让你选npm、yarn、No,I ca...

vue中通过WeixinJSBridge关闭微信公众号当前页面,返回微信公众号首页

之前有个需求,点击菜单进入到微信公众号模块,然后点击返回的时候不知道到哪里去,后来觉得点返回的时候直接关闭页面,但是window.close()并不能关闭页面,然后经过查找资料,发现通过以下方法可以 setTimeout(function() { //这个可以关闭安卓系统的手机 document.addEventListener( "Wei...

vue路由跳转页面的几种方式及其区别

场景:A页面跳转到B页面并携带参数 方案一:声明式导航router-link 1.1不带参数: // 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。 <router-link :to="{name:'home'}"> <router-link :to="{path:'/hom...