vue中如何使用jest單元測(cè)試
當(dāng)我初次聽(tīng)到單元測(cè)試時(shí),心里的第一感覺(jué)就兩個(gè)字nb,然后就是疑惑,這是啥,干啥用,對(duì)代碼又有什么幫助?接下來(lái)我會(huì)細(xì)細(xì)說(shuō)一說(shuō)我在學(xué)習(xí)以及應(yīng)用單元測(cè)試的一些心得。(安裝教程不再敘述,按照文檔教程自行學(xué)習(xí))
文檔推薦
學(xué)習(xí)新知識(shí),有中文文檔當(dāng)然是最好的啦!
組件掛載相關(guān)方法
shallowMount
shallowMount:
創(chuàng)建一個(gè)包含被掛載和渲染的 Vue 組件的 Wrapper。與之對(duì)應(yīng)的還有一個(gè)mount。
shallowMount與mount的區(qū)別:
在文檔中描述為"不同的是被存根的子組件",大白話就是shallowMount不會(huì)加載子組件,不會(huì)被子組件的行為屬性影響該組件。
為什么使用shallowMount而不使用mount:
我認(rèn)為單元測(cè)試的重點(diǎn)在"單元"二字,而不是"測(cè)試",想測(cè)試子組件再為子組件寫(xiě)對(duì)應(yīng)的測(cè)試代碼即可。
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' describe('Foo', () => { ? ? const wrapper = shallowMount(Foo) })
Wrapper(這里只記錄一些我經(jīng)常使用的)
Wrapper
:Wrapper 是一個(gè)包括了一個(gè)掛載組件或 vnode,以及測(cè)試該組件或 vnode 的方法。Wrapper.vm
:這是該 Vue 實(shí)例。你可以通過(guò) wrapper.vm 訪問(wèn)一個(gè)實(shí)例所有的方法和屬性。Wrapper.classes
:返回是否擁有該class的dom或者類名數(shù)組。Wrapper.find
:返回第一個(gè)滿足條件的dom。Wrapper.findAll
:返回所有滿足條件的dom。Wrapper.html
:返回html字符串。Wrapper.text
:返回內(nèi)容字符串。Wrapper.setData
:設(shè)置該組件的初始data數(shù)據(jù)。Wrapper.setProps
:設(shè)置該組件的初始props數(shù)據(jù)。Wrapper.trigger
:用來(lái)觸發(fā)事件。
<template> ?? ?<div class="jest"> ?? ??? ?<div class="name">{{name}}</div> ?? ??? ?<div class="name">{{name}}{{text}}</div> ?? ??? ?<div class="text" @click="add">{{text}}</div> ?? ?</div> </template> <script src="./script.js"> export default { ?? ?name:"Foo", ?? ?props:{ ?? ??? ?name:{ ?? ??? ??? ?type: String, ?? ??? ??? ?default: '王大大' ?? ??? ?} ?? ?}, ? ? data() { ? ? ? ? return { ? ? ? ? ? ? text: 123 ? ? ? ? } ? ? }, ? ? methods:{ ? ? ?? ?add(){ ?? ??? ??? ?this.text += 1 ?? ??? ?} ? ? } } </script>
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' describe('Foo', () => { ? ? const wrapper = shallowMount(Foo) ? ? console.log(Wrapper.classes())?? ?//['jest','name','test'] ? ? console.log(Wrapper.classes('jest'))?? ?//true ? ? console.log(Wrapper.find('name').text())?? ?//返回第一個(gè)class是name的dom的內(nèi)容 ? 王大大 ? ? console.log(Wrapper.findAll('name'))?? ?//返回dom數(shù)組 ? ? console.log(Wrapper.findAll('name').at(0))?? ?//取dom數(shù)組中的第一個(gè) ? ? Wrapper.setData({text : 1}) ? ? console.log(Wrapper.vm.text)?? ?//1 ? ? Wrapper.setProps({name : "李大大"}) ? ? console.log(Wrapper.vm.name)?? ?//李大大 ? ? Wrapper.find('text').trigger("click") ? ? console.log(Wrapper.vm.text) // 2 })
掛載選項(xiàng)
就是shallowMount或者mount的時(shí)候可以設(shè)置一些初始化內(nèi)容。具體可以初始化的全部?jī)?nèi)容請(qǐng)查詢文章開(kāi)始的文檔。
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' const wrapper = shallowMount(Foo, { ?? ?data() { ?? ??? ?return { ?? ??? ??? ?bar: 'my-override' ?? ??? ?} ? }, ? propsData: { ?? ??? ?msg: 'aBC' ? } ? mocks: { ? ? ? ? $route: { ? ? ? ? ? ? query: { ? ? ? ? ? ? ? ? aaa: '1', ? ? ? ? ? ? } ? ? ? ? }, ? ? ? ? $router: { ? ? ? ? ? ? push: jest.fn(), ? ? ? ? ? ? replace: jest.fn(), ? ? ? ? } ? ? } })
jest-api
匹配器
使用不同匹配器可以測(cè)試輸入輸出的值是否符合預(yù)期。
toBe
:判斷是否相等toBeNull
:判斷是否為nulltoBeUndefined
:判斷是否為undefinedtoBeDefined
:與上相反toBeNaN
:判斷是否為NaNtoBeTruthy
:判斷是否為truetoBeFalsy
:判斷是否為falsetoContain
:數(shù)組用,檢測(cè)是否包含toHaveLength
:數(shù)組用,檢測(cè)數(shù)組長(zhǎng)度toEqual
:對(duì)象用,檢測(cè)是否相等toThrow
:異常匹配(沒(méi)用過(guò))
describe('Foo', () => { ?? ?expect(2 + 2).toBe(4) ?? ?expect(null).toBeNull() ?? ?expect(undefined).toBeUndefined() ?? ?let a = 1; ?? ?expect(a).toBeDefined() ?? ?a = 'ada'; ?? ?expect(a).toBeNaN() ?? ?a = true; ?? ?expect(a).toBeTruthy() ?? ?a = false; ?? ?expect(a).toBeFalsy() ?? ?a ?= [1,2,3]; ?? ?expect(a).toContain(2) ?? ?expect(a).toHaveLength(3) ?? ?a = {a:1}; ?? ?expect(a).toEqual({a:1}) })
mock函數(shù)
例如:在一個(gè)vue組件中,ajax請(qǐng)求、路由跳轉(zhuǎn)是常常用到的,但是在單測(cè)代碼中,我們并不能正確的知道他是否執(zhí)行并達(dá)到了預(yù)期的效果,這時(shí)就需要mock函數(shù)。在上文掛載選項(xiàng)中的mocks.$router就是一種mock函數(shù)的應(yīng)用實(shí)例。
mock函數(shù)自然是要使用該函數(shù),下面是一些函數(shù)的常用匹配器
toBeCalledTimes
:判斷函數(shù)被執(zhí)行的次數(shù)toBeCalled
:判斷函數(shù)是否被執(zhí)行
<template> ?? ?<div class="jest" @click="go"></div> </template> <script src="./script.js"> export default { ?? ?name:"Foo", ? ? methods:{ ? ? ?? ?go(){ ?? ??? ??? ?this.$router.push({path:"/a"}) ?? ??? ?} ? ? } } </script>
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' const wrapper = shallowMount(Foo, { ? mocks: { ? ? ? ? $router: { ? ? ? ? ? ? push: jest.fn(), ? ? ? ? ? ? replace: jest.fn(), ? ? ? ? } ? ? } }) wrapper.find(“jest").trigger("click"); expect(wrapper.vm.$router.push).toBeCalled(); wrapper.find(“jest").trigger("click"); expect(wrapper.vm.$router.push).toBeCalledTimes(2);
promise模擬
jest.mock('@root/api'); //模擬api請(qǐng)求函數(shù) import {getList} from '@root/api'; const listJson = JSON.parse(require('fs').readFileSync('./mock/getList.json')); //引入mock好的json數(shù)據(jù) getList.mockResolvedValue(Promise.resolve(listJson)); //模擬promise返回 getList().then(res => { ?? ?expect(res).toEqual(listJson); })
為什么要使用單測(cè)
說(shuō)了這么多,那為什么要使用單測(cè)呢。在看完上面的描述我想大家也是一頭郁悶,單測(cè)有用嗎?答案當(dāng)然是有。下面舉個(gè)例子:
<template> ?? ?<div class="jest"></div> </template> <script src="./script.js"> import {getList} from '@root/api'; export default { ?? ?name:"Foo", ? ? created(){ ? ? ?? ?getList() ? ? ?? ?.then(res => { ? ? ?? ??? ?this.initData(res) ? ? ?? ?}) ? ? }, ? ? methods:{ ?? ??? ?initData(data){ ?? ??? ??? ?data.name = '王大大'; ?? ??? ?} ?? ?} } </script>
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' const wrapper = shallowMount(Foo)
這時(shí)候就會(huì)報(bào)錯(cuò)data.name,因?yàn)閐ata不一定有值。正確案例如下
<template> ?? ?<div class="jest"></div> </template> <script src="./script.js"> import {getList} from '@root/api'; export default { ?? ?name:"Foo", ? ? created(){ ? ? ?? ?getList() ? ? ?? ?.then(res => { ? ? ?? ??? ?this.initData(res) ? ? ?? ?}) ? ? }, ? ? methods:{ ?? ??? ?initData(data = {}){ ?? ??? ??? ?data.name = '王大大'; ?? ??? ?} ?? ?} } </script>
說(shuō)白了就是讓你的代碼邏輯更符合預(yù)期結(jié)果。
總結(jié)
目前在vue中用到的一些基本知識(shí)都已經(jīng)總結(jié)完了,如果以后在工作中使用了新的api,時(shí)間充裕的情況下我會(huì)持續(xù)更新。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue實(shí)現(xiàn)實(shí)時(shí)更新sessionStorage數(shù)據(jù)的示例代碼
這篇文章主要為大家詳細(xì)介紹了Vue如何實(shí)現(xiàn)實(shí)時(shí)更新sessionStorage數(shù)據(jù),文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,需要的可以參考一下2023-06-06vue3中利用Export2Excel將數(shù)據(jù)導(dǎo)出為excel表格
這篇文章主要給大家介紹了關(guān)于vue3中利用Export2Excel將數(shù)據(jù)導(dǎo)出為excel表格的相關(guān)資料,最近項(xiàng)目需要前端來(lái)導(dǎo)出Excel操作,所以給大家總結(jié)下,需要的朋友可以參考下2023-09-09vue打包后,用后端接口報(bào)錯(cuò)304、404問(wèn)題
這篇文章主要介紹了vue打包后,用后端接口報(bào)錯(cuò)304、404問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05vue報(bào)錯(cuò)Not?allowed?to?load?local?resource的解決辦法
這篇文章主要給大家介紹了關(guān)于vue報(bào)錯(cuò)Not?allowed?to?load?local?resource的解決辦法,這個(gè)錯(cuò)誤是因?yàn)閂ue不能加載本地資源的原因,需要的朋友可以參考下2023-07-07Vue 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的鼠標(biāo)拖拽滾動(dòng)效果插件
這篇文章主要介紹了Vue 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的鼠標(biāo)拖拽滾動(dòng)效果插件,幫助大家更好的理解和使用vue框架,感興趣的朋友可以了解下2020-12-12