Vue Test Utils 是 Vue.js 官方的单元测试实用程序库。它提供了一套工具,简化了 Vue.js 组件的测试,使开发人员更容易编写和管理测试。Vue Test Utils 可以与流行的测试框架如 Jest 和 Mocha 一起工作,允许开发人员将 Vue 组件测试集成到他们现有的测试工作流中。
基本内容
主要特性(用来干什么?)
- 挂载和渲染组件: Vue Test Utils 允许您在隔离中挂载组件,这意味着您可以测试单个组件而不必担心其子组件或需要完整的 Vue 应用环境。它还支持浅层挂载,其中子组件被存根,使测试更快并且只关注正在测试的组件。
- 访问 Vue 实例: 当组件被挂载时,Vue Test Utils 提供对 Vue 实例的访问,使得可以检查和与组件的数据、计算属性、方法和生命周期钩子进行交互。
- 事件模拟: 它提供了模拟用户操作(如点击或输入)的实用程序,使测试能够像用户一样与组件进行交互。
- 查找元素: Vue Test Utils 提供了查找组件内元素的方法,既可以使用选择器也可以引用 Vue 组件。这对于断言元素的存在或作为测试的一部分与它们交互非常有用。
- 存根和模拟: 它支持存根子组件,这对于隔离正在测试的组件非常有用。您还可以使用 Jest 或其他模拟库来模拟组件使用的外部依赖或模块。
入门
要开始使用 Vue Test Utils,您需要设置一个 Vue 项目。然后可以在项目中安装 Vue Test Utils 和测试框架(如 Jest)作为开发依赖:
npm install --save-dev @vue/test-utils
安装后,您可以开始使用 Vue Test Utils 和所选的测试框架为 Vue 组件编写测试。
配置Jest
在项目根目录下创建一个名为 jest.config.js 的文件,添加以下配置:
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
testMatch: ['**/tests/unit/**/*.spec.js'],
transform: {
'^.+\\.vue$': 'vue-jest',
'^.+\\.js$': 'babel-jest',
},
};
配置使用 Jest 的 HTML 报告器
npm install --save-dev jest-html-reporters
然后,在你的 jest.config.js 文件中配置报告器:
//HTML 报告器
reporters: [
"default",
["jest-html-reporters", {
publicPath: "./html-report",
filename: "report.html",
expand: true
}]
],
运行测试后,你会在指定的目录(本例中为 ./html-report)下找到一个 HTML 文件,你可以用浏览器打开它查看测试结果。
使用测试运行器和断言库
Vue Test Utils 本身不包含测试运行器或断言库。你需要选择并配置一个测试运行器(如 Jest 或 Mocha)来运行测试用例,以及一个断言库(如 Chai、Expect)来编写断言。
例如,使用 Jest 作为测试运行器,你可以在 package.json 中配置脚本来运行测试:
"scripts": {
"test:unit": "jest"
},
然后,你可以使用 Jest 提供的全局 test 函数和 expect 断言来编写测试用例。
注意事项
- 隔离测试:尽量保持测试的独立性,避免测试间的相互影响。
- 模拟依赖:对外部依赖(如 API 调用)进行模拟,确保测试的可控性和稳定性。
- 测试覆盖率:关注测试覆盖率,但不应追求 100% 覆盖率而忽略了测试质量。
- 持续集成:将测试集成到持续集成 / 持续部署(CI/CD)流程中,确保每次提交都经过测试。
通过遵循这些最佳实践和步骤,你可以有效地利用 Vue Test Utils 来提高你的 Vue 应用或组件的质量和稳定性。
编写测试用例
测试用例通常遵循 Arrange-Act-Assert (AAA) 模式:
- Arrange(准备) :设置测试的初始条件,包括挂载组件。
- Act(执行) :执行某些操作,如模拟用户输入或触发事件。
- Assert(断言) :验证组件的状态或输出是否符合预期。
<template>
<div>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
props: ['msg']
}
</script>
import { mount } from '@vue/test-utils';
import HelloWorld from '@/components/HelloWorld.vue';
describe('HelloWorld', () => {
it('renders the message', () => {
const message = 'Hello Vue!' //测试传入的值
const wrapper = mount(HelloWorld, {
propsData: {
msg: message
}
})
expect(wrapper.text()).toBe('Hello World!') //我们期望得到的值
})
})
这个测试用例的目的是验证一个名为 HelloWorld.vue 的 Vue 组件是否能够正确渲染传递给它的 msg 属性。下面是这段代码的详细解释:
测试用例解释
-
描述测试套件:
describe是 Jest 提供的一个函数,用于声明一个测试套件(test suite)。它接受两个参数:第一个参数是一个字符串,描述了测试套件的名称或正在测试的组件;第二个参数是一个函数,在这个函数内部,你可以定义一系列的测试用例(test cases)。- 在这个例子中,
describe('HelloWorld.vue', () => { ... })表示这个测试套件包含了针对HelloWorld.vue组件的测试。
-
定义测试用例:
it或test是用来定义一个具体的测试用例。它同样接受两个参数:第一个参数是一个描述该测试用例的字符串;第二个参数是一个实际执行测试的函数。it('renders props.msg when passed', () => { ... })定义了一个测试用例,目的是检查HelloWorld.vue组件是否能够正确渲染传入的msg属性。
-
挂载组件并传递 props:
const wrapper = mount(HelloWorld, { props: { msg }, });使用mount函数从 Vue Test Utils 库中创建了HelloWorld组件的一个实例,并通过props选项传递了msg属性。mount函数负责创建一个包裹器(wrapper),它包含了组件的实例以及一些额外的方法和属性,用于测试。
-
断言:
expect(wrapper.text()).toBe('Hello World!')是一个断言。它使用 Jest 的expect函数来检查组件的文本内容是否包含了传递给它的'Hello World!'字符串。如果组件正确渲染了'Hello World!'属性,这个测试就会通过。
总结
这个测试用例展示了如何使用 Vue Test Utils 和 Jest 来测试 Vue 组件的基本行为。通过这种方式,你可以确保你的组件能够按预期接收和渲染 props,从而提高代码的可靠性和质量。随着你继续开发更复杂的组件和应用,编写和维护这样的测试将变得越来越重要。
常用的一些API
深入渲染(Shallow Mount)与完全渲染(Mount)
Vue Test Utils 提供了两种挂载组件的方式:shallowMount 和 mount。
shallowMount 用于浅渲染组件,这意味着它只渲染组件本身,而不渲染其子组件;
mount 则进行完全渲染,包括组件的所有子组件。浅渲染通常用于单元测试,以确保测试的聚焦性和效率;完全渲染更适合集成测试,当你需要测试组件与子组件之间的交互时。
import { shallowMount, mount } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'
import ChildComponent from '@/components/ChildComponent.vue'
// 浅渲染
const wrapper=shallowMount(MyComponent)
expect(wrapper.findComponent(ChildComponent).exists()).toBe(false)
// 完全渲染
const wrapper = mount(MyComponent)
expect(wrapper.findComponent(ChildComponent).exists()).toBe(true)
Wrapper包裹器
Wrapper:Wrapper 是一个包括了一个挂载组件或 vnode,以及测试该组件或 vnode 的方法。
Wrapper.vm:这是该 Vue 实例。你可以通过 wrapper.vm 访问一个实例所有的方法和属性。
Wrapper.element 访问组件的根 DOM 元素
Wrapper.classes:返回是否拥有该class的dom或者类名数组。
Wrapper.find('.foo'):查找第一个匹配选择器的子元素。
Wrapper.findAll('.foo'):返回所有满足条件的dom。
Wrapper.html:返回html字符串。
Wrapper.text:返回内容字符串。
Wrapper.setData:设置该组件的初始data数据。
Wrapper.setProps:设置该组件的初始props数据。
Wrapper.trigger:用来触发事件。
describe()
创建一个分组,可以在这里面编写相应的测试计划。
It()
It 断言 他有两个参数 第一个是字符串 一般用于说明测试组件的那个内容 ,
第二个参数为一个函数 里面用于编写判断,当判断错误时可以精准的查找到错误位置
expect()
Jest为我们提供了expect函数用来包装被测试的方法并返回一个对象, 该对象中包含一系列的匹配器来让我们更方便的进行断言,上面的toBe函数即为一个匹配器
// 判断组件是否存在
expect(wrapper.exists()).toBe(true)
// 判断组件是否可见
expect(wrapper.isVisible()).toBe(true)
// 判断组件是否包含指定的子元素
expect(wrapper.contains('.foo')).toBe(true)
// 判断组件是否包含指定的文本
expect(wrapper.text()).toContain('foo')
匹配器
toBe() 精准匹配toBe和toEqual同样适用于数字。
toBeNull只匹配null
toBeUndefined只匹配undefined
toBeDefine与toBeUndefined相反
toBeTruthy匹配任何if语句为真====>存在类型转换
toBeFalsy匹配任何if语句为假====>存在类型转换
expect(fn).toHaveBeenCalled() // 判断函数是否被调用
expect(fn).toHaveBeenCalledTimes(number) // 判断函数被调用次数
expect(['one','two']).toContain('one'); // 含有某个元素
toBeGreaterThan()大于
toBeGreaterThanOrEqual()大于等于
toBeLessThan()小于
toBeLessThanOrEqual()小于等于
toMatch()测试字符串,传递的参数是正则表达式
事件处理
Trigger()
Vue Test Utils 允许你模拟用户事件,如点击、输入等,以测试组件对这些事件的响应。你可以使用 trigger 方法来模拟事件。
test('msg should be changed by Emit', () => {
const button = wrapper.findAll('button').at(1)
button.trigger('click')
expect(wrapper.emitted()).toHaveProperty('reset')
})