vue+jest+vue-test-utils 单元测试
npm install --save-dev jest @vue/test-utils
//package.json
"scripts": {
"test": "jest",
}
npm install --save-dev vue-jest
const path = require('path'); module.exports = {
verbose: true,
testURL: 'http://localhost/',
rootDir: path.resolve(__dirname, '../../../'),
moduleFileExtensions: [
'js',
'json',
'vue',
],
testMatch: [ // 匹配测试用例的文件
'<rootDir>/src/test/unit/specs/*.spec.js',
],
transform: {
'^.+\\.js$': 'babel-jest',
'.*\\.(vue)$': 'vue-jest',
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e',
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
}, };
//ATest.vue组件
<template>
<div>
<Checkbox class="checkAlls" @on-change="checkboxChange" v-model="checkAll">全选</Checkbox>
</div>
</template>
<script>
export default {
name: 'ATest',
data() {
return {
checkAll: false,
};
},
methods: {
checkboxChange(value) {
this.$emit('on-change', value);
},
},
};
</script>
import { mount, createLocalVue } from '@vue/test-utils';
import ATest from '@/components/ATest.vue';
import iviewUI from 'view-design'; const localVue = createLocalVue();
localVue.use(iviewUI); describe('ATest.vue',()=>{
const wrapper =mount(ATest, {
localVue
}); it("事件被正常触发",()=>{
const stub = jest.fn();
wrapper.setMethods({ checkboxChange: stub });
//触发自定义事件
wrapper.find(".checkAlls").vm.$emit("on-change");
wrapper.setData({checkAll: true});
expect(wrapper.vm.checkAll).toBe(true);
})
})
- mount()
- shallowMount()
//App.vue
<template>
<div id="app">
<Page :messages="messages"></Page>
</div>
</template>
//子组件
<template>
<div>
<p v-for="message in messages" :key="message">{{message}}</p>
</div>
</template>
//测试用例App.spec.js
import { mount } from 'vue-test-utils';
import App from '@/App';
describe('App.test.js', () => {
let wrapper;
let vm;
beforeEach(() => {
wrapper = mount(App);
vm = wrapper.vm;
wrapper.setProps({ messages: ['Cat'] })
});
// 为App的单元测试增加快照(snapshot):
it('has the expected html structure', () => {
expect(vm.$el).toMatchSnapshot()
})
});
exports[`App.test.js has the expected html structure 1`] =
` <div id="app" > <div> <p> Cat </p> </div> </div> `;
exports[`App.test.js has the expected html structure 1`] =
` <div id="app" > <!----> </div> `;
- createLocalVue
import { createLocalVue, shallowMount } from '@vue/test-utils'import Foo from './Foo.vue'
const localVue = createLocalVue()const wrapper = shallowMount(Foo, {
localVue,
mocks: { foo: true }})expect(wrapper.vm.foo).toBe(true)
const freshWrapper = shallowMount(Foo)expect(freshWrapper.vm.foo).toBe(false)
- 选择器 (详细看Vue-Test-Utils官网介绍)
- $route 和 $router
import { mount} from '@vue/test-utils'
import Test from '@/components/common/Test.vue';
describe('Test.vue',()=>{
const wrapper = mount(Test, {
mocks: {
$route: { path: '/login' }
}
})
it("test", ()=>{
expect(wrapper.vm.$route.path).toMatch('/login')
})
})
- 状态管理Vuex
import Vuex from 'vuex';
import {mount, createLocalVue} from '@vue/test-utils'; const localVue = createLocalVue();
localVue.use(Vuex);
describe('Test.vue',()=>{
let wrapper;
let getters;
let store;
let action;
let mutations;
let option;
beforeEach(()=>{
state = {
name: '张三'
}
getters = {
GET_NAME: ()=> '张三'
}
mutations = {
SET_NAME: jest.fn()
}
action = {
setName: jest.fn()
}
store = new Vuex.Store({
getters,
mutations,
action
})
option = {
store,
localVue
}
wrapper = mount(Test, option)
}) it("测试vuex", ()=>{
expect(getters.GET_Name()).toEqual('张三');
wrapper.vm.$store.state.name= "李四";
expect(wrapper.vm.name).toMatch('李四');
wrapper.find('.btn').trigger('click')
expect(actions.setName).toHaveBeenCalled()
wrapper.find({ref: 'testComp'}).vm.$emit('on-select');
expect(mutations.SET_NAME).toBeCalled()
}) })
- wrapper
- beforeEach(fn) 在每一个测试之前需要做的事情,比如测试之前将某个数据恢复到初始状态
- afterEach(fn) 在每一个测试用例执行结束之后运行
- beforeAll(fn) 在所有的测试之前需要做什么
- afterAll(fn) 在测试用例执行结束之后运行
//Test.vue
mounted() {
this.getDataList();
}, methods: {
getDataList() {
this.$api.data.getData().then((res) => {
this.List= res.data;
});
} import {shallowMount, createLocalVue} from '@vue/test-utils';
const localVue = createLocalVue();
//axios请求
jest.mock('../data.js', ()=>({
getData: () => Promise.resolve({data:{name:'张三'}})
}))
describe('Test.vue',()=>{
const option;
let wrapper =shallowMount(Test, option)
it("异步接口被正常执行", async()=>{
const getDataList= jest.fn();
option.methods = {getDataList};
shallowMount(Test, option);
await expect(getDataList).toBeCalled();
}) it('测试异步接口的返回值', () => {
return localVue.nextTick().then(() => {
expect(wrapper.vm.List).toEqual( {name:'张三'});
})
}) })
[vue-test-utils]: find did not return .btn, cannot call trigger() on empty Wrapper
//出现该问题的时候,除了要确保你的组件确实存在该类名的情况,还要确保存在v-if的时候是否为true,如果为false,只需要在单测里将其设置为true,该问题便可解决
"ReferenceError: sessionStorage is not defined"
//出现该问题只需要去模拟本地存储就可以了,npm提供了一个模拟本地存储数据的依赖包mock-local-storage,安装后在单测文件里导入即可
//import 'mock-local-storage';
//包地址:https://www.npmjs.com/package/mock-local-storage
TypeError: Cannot read property xxxx of undefined
//这个问题的一般解决方法是直接mock数据
%stmts是语句覆盖率(statement coverage):是否每个语句都执行了?
%Branch分支覆盖率(branch coverage):是否每个if代码块都执行了?
%Funcs函数覆盖率(function coverage):是否每个函数都调用了?
%Lines行覆盖率(line coverage):是否每一行都执行了?
- npx jest --init 生成配置文件jest.config.js
- package.json添加上
--coverage
这个参数
//修改package.json
"scripts": {
"test": "jest --coverage"
}
npm run test之后会生成coverage文件
然后再网页打开index.html,就会看到下图
三种颜色分别代表不同比例的覆盖率(<50%红色,50%~80%灰色, ≥80%绿色)
点击文件名可以查看代码的执行情况,
旁边显示的1x代表执行的次数
vue+jest+vue-test-utils 单元测试的更多相关文章
- 前端单元测试,以及给现有的vue项目添加jest + Vue Test Utils的配置
文章原址:https://www.cnblogs.com/yalong/p/11714393.html 背景介绍: 以前写的公共组件,后来需要添加一些功能,添加了好几次,每次修改我都要测试好几遍保证以 ...
- 如何为我的VUE项目编写高效的单元测试--Jest
Unit Testing(单元测试)--Jest 一个完整的测试程序通常由几种不同的测试组合而成,比如end to end(E2E)测试,有时还包括整体测试.简要测试和单元测试.这里要介绍的是Vue中 ...
- vue项目工具文件utils.js javascript常用工具类,javascript常用工具类,util.js
vue项目工具文件utils.js :https://blog.csdn.net/Ajaxguan/article/details/79924249 javascript常用工具类,util.js : ...
- Vue 项目 Vue + restfulframework
Vue 项目 Vue + restfulframework 实现登录认证 - django views class MyResponse(): def __init__(self): self.sta ...
- vue学习之用 Vue.js + Vue Router 创建单页应用的几个步骤
通过vue学习一:新建或打开vue项目,创建好项目后,接下来的操作为: src目录重新规划——>新建几个页面——>配置这几个页面的路由——>给根实例注入路由配置 src目录重整 在项 ...
- vue --- 解读vue的中webpack.base.config.js
const path = require('path') const utils = require('./utils')// 引入utils工具模块,具体查看我的博客关于utils的解释,utils ...
- vue — 创建vue项目
创建vue项目 在程序开发中,有三种方式创建vue项目,本地引入vuejs.使用cdn引入vuejs.使用vue-cli创建vue项目.其中vue-cli可以结合webpack打包工具使用,大大方便了 ...
- vue入门 vue与react和Angular的关系和区别
一.为什么学习vue.js vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn.vuejs.org/ 手册:http://cn.vuejs.org/ ...
- Vue (三) --- Vue 组件开发
------------------------------------------------------------------好心情,会让你峰回路转. 5. 组件化开发 5.1 组件[compo ...
随机推荐
- java接口和抽象类的比较
相同点: 都位于继承的顶端,用于被其他实现或继承; 都不能实例化; 都包含抽象方法,其子类都必须覆写这些抽象方法; 区别: 抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口 ...
- 解析PHP跳出循环的方法以及continue、break、exit的区别介绍
本篇文章是对PHP跳出循环的方法以及continue.break.exit的区别进行了详细的分析介绍,需要的朋友参考下 PHP中的循环结构大致有for循环,while循环,do{} while 循 ...
- java 反射的概念
反射的引入: Object obj = new Student(); 若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法: 1.若编译和运行类型 ...
- 通过作用域链解析js函数一些难以理解的的作用域问题
基本原理 js函数在执行时,系统会创建一个隐式的属性scope,scope中存储的是函数的作用域链. 通过对这个scope的分析,就能解释JavaScript中许多难以理解的问题: 例1: funct ...
- linux获知当前时间
内核代码能一直获取一个当前时间的表示, 通过查看 jifies 的值. 常常地, 这个值只代 表从最后一次启动以来的时间, 这个事实对驱动来说无关, 因为它的生命周期受限于系统 的 uptime. 如 ...
- 2018-2-13-win10-UWP-Markdown-含源代码
title author date CreateTime categories win10 UWP Markdown 含源代码 lindexi 2018-2-13 17:23:3 +0800 2018 ...
- springboot多对一关系映射
原文:https://blog.csdn.net/h993438890/article/details/89146483 spring boot项目的创建省略创建两张表t_user 字段 主键id,u ...
- JavaSE基础知识---常用对象API之String类
一.String类 Java中用String类对字符串进行了对象的封装,这样的好处在于对象封装后可以定义N多属性和行为,就可以对字符串这种常见的数据进行方便的操作. 格式:(1)String s1 = ...
- js 处理json
json 分为两种结构 数组 对象 对象 { } 对象里的键值对 1.键值对之间用冒号链接 2.键必须用“”包裹 3.值如果是字符串 就用“”包裹 如果是数字 则不需要 4.键值对 ...
- Sending Packets LightOJ - 1321 (期望计算)
题面: Alice and Bob are trying to communicate through the internet. Just assume that there are N route ...