在Vue 项目中引入Jest测试框架

1,570 阅读3分钟

在Vue 项目中引入Jest测试框架

1. 安装Jest

    1. 如果你是新项目 假如你是vue-cli3/4,在创建项目时会提示使用的测试框架,我选择的是Jest
    1. 如果你是老项目 安装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 官方的单元测试实用工具库

    1. 生成配置文件 生成一个配置文件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,然后把路由表打印出来发现没有这个路由,所以直接把异步加载的方式改掉

4. 如果提示你找不到你的东西,那就在测试文件中引入注入到测试文件的Vue中

4. 运行通过

参考:juejin.cn/post/684490…

参考:dwatow.github.io/2019/11-26-…