Skip to content

单元测试是项目开发中一个非常重要的环节,完整的测试能为代码和业务提供质量保证,减少 Bug 的出现。
下面带领大家在 Vite + Vue3 + TypeScript 的项目中集成单元测试工具。

安装核心依赖

我们使用 Vue 官方提供的 vue-test-utils 和社区流行的测试工具 jest 来进行 Vue 组件的单元测试。

  • vue-test-utils The next iteration of Vue Test Utils. It targets Vue 3.
  • jest Delightful JavaScript Testing.
  • vue-jest Jest Vue transformer
  • ts-jest A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.

安装这些工具为开发依赖(devDependencies):

javascript
npm i @vue/test-utils@next jest vue-jest@next ts-jest -D
npm i @vue/test-utils@next jest vue-jest@next ts-jest -D

创建 jest 配置文件

在项目根目录下新建 jest.config.js 文件:

javascript
module.exports = {
	moduleFileExtensions: ['vue', 'js', 'ts'],
	preset: 'ts-jest',
	testEnvironment: 'jsdom',
	transform: {
		'^.+\\.vue$': 'vue-jest',
		// vue 文件用 vue-jest 转换
		'^.+\\.ts$': 'ts-jest',
		// ts 文件用 ts-jest 转换
	},
	// 匹配 __tests__ 目录下的 .js/.ts 文件 或其他目录下的 xx.test.js/ts xx.spec.js/ts
	testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts)$',
}
module.exports = {
	moduleFileExtensions: ['vue', 'js', 'ts'],
	preset: 'ts-jest',
	testEnvironment: 'jsdom',
	transform: {
		'^.+\\.vue$': 'vue-jest',
		// vue 文件用 vue-jest 转换
		'^.+\\.ts$': 'ts-jest',
		// ts 文件用 ts-jest 转换
	},
	// 匹配 __tests__ 目录下的 .js/.ts 文件 或其他目录下的 xx.test.js/ts xx.spec.js/ts
	testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts)$',
}

创建单元测试文件

在上面的 jest.config.js 文件中,我们配置只匹配 tests 目录下的任意 .ts 文件或其他目录下的 xx.test.ts/xx.spec.ts 文件进行单元测试。
这里,我们在项目根目录下创建 tests 目录来存储单元测试文件

bash
├── src/
└── tests/                           // 单元测试目录
├── Test.spec.ts                 // Test 组件测试
├── src/
└── tests/                           // 单元测试目录
├── Test.spec.ts                 // Test 组件测试
  • Test.vue
vue
<template>
	<div class="test-container page-container">
		<div class="page-title">Unit Test Page</div>
		<p>count is: {{ count }}</p>
		<button @click="increment">increment</button>
	</div>
</template>
<script lang="ts">
import {defineComponent, ref} from 'vue'
export default defineComponent({
	name: 'Vuex',
	setup() {
		const count = ref<number>(0)
		const increment = () => {
			count.value += 1
		}
		return {count, increment}
	},
})
</script>
<template>
	<div class="test-container page-container">
		<div class="page-title">Unit Test Page</div>
		<p>count is: {{ count }}</p>
		<button @click="increment">increment</button>
	</div>
</template>
<script lang="ts">
import {defineComponent, ref} from 'vue'
export default defineComponent({
	name: 'Vuex',
	setup() {
		const count = ref<number>(0)
		const increment = () => {
			count.value += 1
		}
		return {count, increment}
	},
})
</script>
  • Test.spec.ts
typescript
import {mount} from '@vue/test-utils'
import Test from '../src/views/Test.vue'
test('Test.vue', async () => {
	const wrapper = mount(Test)
	expect(wrapper.html()).toContain('Unit Test Page')
	expect(wrapper.html()).toContain('count is: 0')
	await wrapper.find('button').trigger('click')
	expect(wrapper.html()).toContain('count is: 1')
})
import {mount} from '@vue/test-utils'
import Test from '../src/views/Test.vue'
test('Test.vue', async () => {
	const wrapper = mount(Test)
	expect(wrapper.html()).toContain('Unit Test Page')
	expect(wrapper.html()).toContain('count is: 0')
	await wrapper.find('button').trigger('click')
	expect(wrapper.html()).toContain('count is: 1')
})

集成 @types/jest

如上图,我们使用 VSCode / WebStrom / IDEA 等编辑器时,在单元测试文件中,IDE 会提示某些方法不存在(如 test、describe、it、expect 等),安装 @types/jest 即可解决。

bash
npm i @types/jest -D
npm i @types/jest -D

TypeScript 的编译器也会提示 jest 的方法和类型找不到,我们还需把 @types/jest 添加根目录下的 ts.config.json(TypeScript 配置文件)中:

javascript
{
  "compilerOptions": {
    ...
  "types": ["vite/client", "jest"]
   },
}
{
  "compilerOptions": {
    ...
  "types": ["vite/client", "jest"]
   },
}

添加 eslint-plugin-jest

因为我们在项目中集成了 ESLint,如上图很明显是没通过 ESLint 规则检验。因此,我们还需要在 ESLint 中增加 eslint-plugin-jest 插件来解除对 jest 的校验。

  • 安装 eslint-plugin-jestnpm i eslint-plugin-jest -D
  • 添加 eslint-plugin-jest 到 ESLint 配置文件 .eslintrc.js 中
javascript
module.exports = {
  ...
  extends: [
  ...
  'plugin:jest/recommended'
  ],
    ...
}
module.exports = {
  ...
  extends: [
  ...
  'plugin:jest/recommended'
  ],
    ...
}

现在,我们的单元测试代码就不会有错误提示信息了 ؏؏☝ᖗ 乛 ◡ 乛 ᖘ☝؏؏

执行单元测试

在根目录下 package.json 文件的 scripts 中,添加一条单元测试命令: "test": "jest"。

执行命令 npm run test 即可进行单元测试,jest 会根据 jest.config.js 配置文件去查找 tests 目录下的 .ts 文件或其他任意目录下的 .spec.ts 和 .test.ts 文件,然后执行单元测试方法。
你可以在 jest.config.js 配置文件中,自由配置单元测试文件的目录。

  • 单元测试全部通过时的终端显示信息
  • 单元测试未全部通过时的终端显示信息

当单元测试没有全部通过时,我们需要根据报错信息去优化对应组件的代码,进一步提高项目健壮性。但是写单元测试是件比较痛苦的事,我个人觉得也没必要全部组件都写单元测试,根据项目实际情况有针对性去写就行了。

单元测试约束

前面,我们使用 husky 在 Git 的 pre-commit 和 commit-msg 阶段分别约束代码风格规范和提交信息规范。这一步,我们在 pre-push 阶段进行单元测试,只有单元测试全部通过才让代码 push 到远端仓库,否则终止 push。
使用 husky 命令在 .husky 目录下自动创建 pre-push hook 文件,并在此执行单元测试命令 npm run test。

bash
npx husky add .husky/pre-push "npm run test $1"
npx husky add .husky/pre-push "npm run test $1"

现在,我们在 git push 时就能先进行单元测试了,只有单元测试全部通过,才能成功 push。