[TOC]
知识点
- 将 mock 对象断言为特定类型 使用 jest.Mocked
- 使用 it.only 来指定测试的 case
-
测试内容
触发事件
- trigger 方法
- 测试界面是否更新
- 特别注意 DOM 更新是个异步的过程
- 使用 async await
- 更新表单
- setValue 方法
- 验证事件是否发送
- emitted 方法
测试异步请求
beforeAll
afterAll
let wrapper: VueWrapper<any>; describe('HelloWorld.vue', () => { // 在多个 case 运行之前执行,只执行一次,由于这样会让所有的用例使用一个 `warpper` 实例,可能会造成错误。 beforeAll(() => { // 获取组件 wrapper = shallowMount(HelloWorld, { props: { msg }, }); }); // 在多个 case 运行之后执行,只执行一次 afterAll(() => {}); });
钩子用于每个测试用例测试准备
beforeEach
afterEach
let wrapper: VueWrapper<any>; describe('HelloWorld.vue', () => { beforeEach(() => { // 获取组件 wrapper = shallowMount(HelloWorld, { props: { msg }, }); }); afterEach(() => { mockAxios.get.mockReset(); }); });
测试建议
如果一个测试失败了,需要注意
它是否是唯一在运行的用例,使用 only 单独运行一次, skip 跳过一个用例
- 如果单独运行没问题,整体运行出错,应该检查 beforeEach ,beforeAll 等全局钩子中的逻辑是否有问题,判断是否需要清空共享状态。
测试组件
```javascript{{ msg }}
{{ msg }}
- {{ todo }}
loading
{{ user?.data?.username }}
error
<a name="N4faT"></a>
## 触发事件 trigger
```javascript
import { shallowMount, mount, VueWrapper } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
import hello from '@/components/hello.vue'
jest.mock('axios')
let wrapper: VueWrapper<any>
const msg = 'new message'
describe('HelloWorld.vue', () => {
beforeEach(() => {
// 获取组件
wrapper = shallowMount(HelloWorld, {
props: { msg },
})
})
it('renders props.msg when passed', async () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
props: { msg },
})
//触发事件 trigger是一个异步的过程 记得加async await
await wrapper.get('button').trigger('click')
expect(wrapper.get('button').text()).toBe('1')
})
})
更新表单 setValue
import { shallowMount, mount, VueWrapper } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
import hello from '@/components/hello.vue'
jest.mock('axios')
let wrapper: VueWrapper<any>
const msg = 'new message'
describe('HelloWorld.vue', () => {
...
it('should add todo when fill the input and click the add button', async () => {
const todoContent = 'haha'
//setValue 赋值
await wrapper.get('input').setValue(todoContent)
//wrapper.get('input').element 得到一个dom节点
expect(wrapper.get('input').element.value).toBe(todoContent)
//.add-todo
await wrapper.get('.add-todo').trigger('click')
//数组长度 toHaveLength
expect(wrapper.findAll('li')).toHaveLength(1)
expect(wrapper.get('li').text()).toBe(todoContent)
})
})
验证事件 emitted
...
// 断言 触发了 名为 send 的 emit 事件
expect(wrapper.emitted()).toHaveProperty('send')
// 获取 send 事件的 对象
const events = wrapper.emitted('send')!
console.log('events', events)
// 检查对象内容是否相同使用 toEqual, toBe 要求类型也相同
expect(events[0]).toEqual([todoContent])
异步请求
...
// 使用 it.only 来指定测试的 case
it.only('should load user message when click the load button', async () => {
mockAxios.get.mockResolvedValueOnce({
data: {
username: 'haha',
},
})
await wrapper.get('.load-user').trigger('click')
//请求是否被调用
expect(mockAxios.get).toHaveBeenCalled()
//exists 是否存在;toBeTruthy 匹配任何if语句为真
expect(wrapper.find('.loading').exists()).toBeTruthy()
// 让 promise 完成,并且界面更新完成
await flushPromises()
//toBeFalsy 匹配任何if语句为假
expect(wrapper.find('.loading').exists()).toBeFalsy()
expect(wrapper.get('.user-name').text()).toBe('haha')
})
//skip跳过一些用例
it.skip('should load user message when click the error button', async () => {
//处理error的情况
mockAxios.get.mockRejectedValueOnce('error')
await wrapper.get('.load-user').trigger('click')
//请求是否被调用
expect(mockAxios.get).toHaveBeenCalled()
await flushPromises()
//toBeFalsy 匹配任何if语句为假
expect(wrapper.find('.loading').exists()).toBe(false)
expect(wrapper.find('.error').exists()).toBe(true)
})