<!-- 单元测试 --><template><h1>{{ msg }}</h1><button @click="setCount">{{ count }}</button><input type="text" v-model="todo"><button class="addTodo" @click="addTodo">add</button><ul><li v-for="(todo,index) in todos" :key="index">{{todo}}</li></ul><button class="loadUser" @click="loadUser">load</button><p v-if="user.loading" class="loading">Loading</p><div v-else class="userName" >{{user.data?.userName}}</div><p v-if="user.error" class="error">error!</p><Hello msg="1234" /></template><script lang="ts">import { defineComponent, reactive, ref } from "vue";import axios from 'axios';import Hello from "./Hello.vue";export default defineComponent({name: "",components: {Hello,},props: {msg: String},emits: ['send'],setup(props,context) {const count = ref(1);const todo = ref('')const todos = ref<string[]>([])const user = reactive({data: null as any,loading: false,error: false,})const setCount = () => {count.value++}const addTodo = () => {if(todo.value) {todos.value.push(todo.value)context.emit('send', todo.value)}}const loadUser = () => {user.loading = trueaxios.get('https:/ljsonplaceholder.typicode.com/users/1').then(res=>{console.log(res);user.data = res.data}).catch(() => {user.error = true}).finally(() => {user.loading = false})}return {count,todo,todos,setCount,addTodo,user,loadUser};},});</script><style lang="scss" scoped></style>
以下组件为例子,该组件有以下功能点:
1、根据props的msg显示到组件
2、点击setCount按钮,实现自增1
3、TODO功能:
- 输入
input,页面正常显示输入内容。 - 点击
addTodo按钮,li的长度+1,显示输入内容。
4、点击loadUser按钮,发出请求用户数据请求,按钮处于loading状态。数据返回之后,元素.userName显示返回的用户信息。
所以可以编写以上4个测试用例。
重点注意第四点,axios请求测试的方法。mockAxios.get.mockResolvedValueOnce({ data: { username: 'viking'}})和mockAxios.get.mockRejectedValueOnce('error')分别模拟axios的正确返回和错误返回。
import { shallowMount, VueWrapper } from '@vue/test-utils'import axios from 'axios'import flushPromises from 'flush-promises'import HelloWorld from '@/components/HelloWorld.vue'import Hello from '@/components/Hello.vue'jest.mock('axios')const mockAxios = axios as jest.Mocked<typeof axios>const msg = 'new message'let wrapper: VueWrapper<any>describe('HelloWorld.vue', () => {beforeAll(() => {wrapper = shallowMount(HelloWorld, {props: { msg }})})it('renders props.msg when passed', () => {expect(wrapper.get('h1').text()).toBe(msg)expect(wrapper.findComponent(Hello).exists()).toBeTruthy()})it('should update the count when clicking the button', async () => {await wrapper.get('button').trigger('click')expect(wrapper.get('button').text()).toBe('2')})it('should add todo when fill the input and click the add button', async () => {const todoContent = 'buy milk'await wrapper.get('input').setValue(todoContent)expect(wrapper.get('input').element.value).toBe(todoContent)await wrapper.get('.addTodo').trigger('click')expect(wrapper.findAll('li')).toHaveLength(1)expect(wrapper.get('li').text()).toBe(todoContent)console.log(wrapper.emitted())expect(wrapper.emitted()).toHaveProperty('send')const events = wrapper.emitted('send')expect(events[0]).toEqual([todoContent])})it('should load user message when click the load button', async () => {mockAxios.get.mockResolvedValueOnce({ data: { username: 'viking'}})await wrapper.get('.loadUser').trigger('click')expect(mockAxios.get).toHaveBeenCalled()expect(wrapper.find('.loading').exists()).toBeTruthy()await flushPromises()// 界面更新完毕expect(wrapper.find('.loading').exists()).toBeFalsy()expect(wrapper.get('.userName').text()).toBe('viking')})it('should load error when return promise reject', async () => {mockAxios.get.mockRejectedValueOnce('error')await wrapper.get('.loadUser').trigger('click')expect(mockAxios.get).toHaveBeenCalledTimes(1)await flushPromises()expect(wrapper.find('.loading').exists()).toBe(false)expect(wrapper.find('.error').exists()).toBe(true)})afterEach(() => {mockAxios.get.mockReset()})})
