在Vue 项目中引入Jest测试框架
1. 安装Jest
-
- 如果你是新项目
假如你是vue-cli3/4,在创建项目时会提示使用的测试框架,我选择的是Jest
- 如果你是新项目
假如你是vue-cli3/4,在创建项目时会提示使用的测试框架,我选择的是Jest
-
- 如果你是老项目 安装Jest npm install --save-dev jest 复制代码安装vue-jest npm install --save-dev vue-jest //告诉 Jest 如何处理 *.vue 文件 复制代码 注意:vue-jest 目前并不支持 vue-loader 所有的功能,比如自定义块和样式加载。
安装babel-jest npm install --save-dev babel-jest // 支持测试中使用 ES modules 语法和 stage-x 的特性 复制代码安装jest-transform-stub npm install --save-dev jest-transform-stub// 使用这个模块避免导入非JavaScript文件时错误 复制代码安装vue/test-utils
npm install --save-dev @vue/test-utils // Vue.js 官方的单元测试实用工具库
-
- 生成配置文件 生成一个配置文件jest.config.js,以下是自己项目的一个配置
module.exports = {
// Automatically clear mock calls and instances between every test
clearMocks: true,
// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
// An array of regexp pattern strings used to skip coverage collection
coveragePathIgnorePatterns: [
'/node_modules/'
],
// A set of global variables that need to be available in all test environments
globals: {
},
// An array of file extensions your modules use
moduleFileExtensions: [
'js',
'json',
'jsx',
'vue'
],
// A map from regular expressions to module names that allow to stub out resources with a single module
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
roots: [
'<rootDir>'
],
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: ['<rootDir>/tests/global.js'],
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
snapshotSerializers: ['jest-serializer-vue'],
// The test environment that will be used for testing
testEnvironment: 'jsdom',
// The glob patterns Jest uses to detect test files
testMatch: [
'**/tests/unit/**/*.spec.[jt]s?(x)',
'**/__tests__/**/*.js?(x)',
'**/?(*.)+(spec).js?(x)'
],
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
testURL: 'http://localhost/',
// A map from regular expressions to paths to transformers
transform: {
'^.+\\.vue$': require.resolve('vue-jest'), // 告诉Jest用 vue-jest 处理 `*.vue` 文件
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
require.resolve('jest-transform-stub'),
'^.+\\.js?$': require.resolve('babel-jest') //来告诉 Jest 用 babel-jest 处理 JavaScript 测试文件
},
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
transformIgnorePatterns: [
'/node_modules/(?!vant|@babel|mint-ui)'
]
};
2. 配置自己项目测试组件/路由组件
1. 测试的组件中使用了router和store
使用 createLocalVue 方法设置隔离的router和store
// import {mount,createLocalVue} from '@vue/test-utils';
// import App from '../../src/app.vue';
// import VueRouter from 'vue-router';
// import routers from "../../src/router"
// const localVue = createLocalVue()
// localVue.use(VueRouter)
// // require('jsdom-global')();
// describe('App', () => {
// test('renders props.msg when passed', () => {
// const msg = 'new message';
// const router = new VueRouter({ routers })
// const wrapper = mount(App, {
// propsData: {
// selecData: {
// paramObj: "123442",
// allLoaded: true,
// courseList: [],
// tempArr: [],
// page: 1
// }
// },
// localVue,
// router
// })
// ;
// expect(wrapper.element).toBeTruthy();
// })
// });
jest.setTimeout(1000);
import { mount, createLocalVue, config } from '@vue/test-utils';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import App from '../../src/App.vue';
import rule from '../../src/pages/rule/rule';
import medal from '../../src/pages/medal/medal';
import routes from '../../src/router/routers';
import store from '../../src/store';
import Vue from "vue";
import Mui from 'vue-awesome-mui';
config.showDeprecationWarnings = false;
const localVue = createLocalVue();
localVue.use(VueRouter);
localVue.use(Vuex);
localVue.use(Mui);
// console.log("-------routes--------",routes);
describe('Actions.vue', () => {
const router = new VueRouter({
mode: 'history',
routes,
});
window.eventBus = new Vue();
// console.log("window.eventBus",window.eventBus);
it('route path: /medal, component: Medal', async () => {
const wrapper = mount(App,{localVue,router,store});
router.push('/medal');
await wrapper.vm.$nextTick();
// console.log("*****************wrapper.find(Rule)********************",router);
expect(wrapper.find(medal).exists()).toBe(true);
});
it('route path: /rule, component: Rule', async () => {
const wrapper = await mount(App,{localVue,router,store});
router.push('/rule');
await wrapper.vm.$nextTick();
// console.log("wrapper.find(Rule)",wrapper.find(Rule));
expect(wrapper.find(rule).exists()).toBe(true);
});
});
2. 简单组件
import { shallowMount } from "@vue/test-utils"
import NestedRoute from "@/components/NestedRoute.vue"
import routes from "@/routes.js"
describe("NestedRoute", () => {
it("renders a username from query string", () => {
const username = "alice"
const wrapper = shallowMount(NestedRoute)
expect(wrapper.find(".username").text()).toBe(username)
})
})
3. 遇到的问题
1. 安装的UI包无法编译问题
这时候要在配置文件中把这个UI组件忽略,不进行测试
2. 语法报错
这时候可能是你的Babel没有配置好,或者是使用的版本不对,又或者是某一个包里面与你安装的版本不对
3. 测试时找不到路由组件
因为项目中我使用的import()异步加载路由组件,导致在运行测试代码的时候总是提示需要true,但是你传入的是一个false,然后把路由表打印出来发现没有这个路由,所以直接把异步加载的方式改掉