<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
當我初次聽到單元測試時,心裡的第一感覺就兩個字nb,然後就是疑惑,這是啥,幹啥用,對程式碼又有什麼幫助?接下來我會細細說一說我在學習以及應用單元測試的一些心得。(安裝教學不再敘述,按照檔案教學自行學習)
學習新知識,有中文檔案當然是最好的啦!
shallowMount
shallowMount:
建立一個包含被掛載和渲染的 Vue 元件的 Wrapper。與之對應的還有一個mount。
shallowMount與mount的區別:
在檔案中描述為"不同的是被存根的子元件",大白話就是shallowMount不會載入子元件,不會被子元件的行為屬性影響該元件。
為什麼使用shallowMount而不使用mount:
我認為單元測試的重點在"單元"二字,而不是"測試",想測試子元件再為子元件寫對應的測試程式碼即可。
import { shallowMount } from '@vue/test-utils' import Foo from './Foo.vue' describe('Foo', () => { const wrapper = shallowMount(Foo) })
Wrapper(這裡只記錄一些我經常使用的)
Wrapper
:Wrapper 是一個包括了一個掛載元件或 vnode,以及測試該元件或 vnode 的方法。Wrapper.vm
:這是該 Vue 範例。你可以通過 wrapper.vm 存取一個範例所有的方法和屬性。Wrapper.classes
:返回是否擁有該class的dom或者類名陣列。Wrapper.find
:返回第一個滿足條件的dom。Wrapper.findAll
:返回所有滿足條件的dom。Wrapper.html
:返回html字串。Wrapper.text
:返回內容字串。Wrapper.setData
:設定該元件的初始data資料。Wrapper.setProps
:設定該元件的初始props資料。Wrapper.trigger
:用來觸發事件。<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()) //返回第一個class是name的dom的內容 王大大 console.log(Wrapper.findAll('name')) //返回dom陣列 console.log(Wrapper.findAll('name').at(0)) //取dom陣列中的第一個 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 })
掛載選項
就是shallowMount或者mount的時候可以設定一些初始化內容。具體可以初始化的全部內容請查詢文章開始的檔案。
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(), } } })
匹配器
使用不同匹配器可以測試輸入輸出的值是否符合預期。
toBe
:判斷是否相等toBeNull
:判斷是否為nulltoBeUndefined
:判斷是否為undefinedtoBeDefined
:與上相反toBeNaN
:判斷是否為NaNtoBeTruthy
:判斷是否為truetoBeFalsy
:判斷是否為falsetoContain
:陣列用,檢測是否包含toHaveLength
:陣列用,檢測陣列長度toEqual
:物件用,檢測是否相等toThrow
:異常匹配(沒用過)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函數
例如:在一個vue元件中,ajax請求、路由跳轉是常常用到的,但是在單測程式碼中,我們並不能正確的知道他是否執行並達到了預期的效果,這時就需要mock函數。在上文掛載選項中的mocks.$router就是一種mock函數的應用範例。
mock函數自然是要使用該函數,下面是一些函數的常用匹配器
toBeCalledTimes
:判斷函數被執行的次數toBeCalled
:判斷函數是否被執行<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請求函數 import {getList} from '@root/api'; const listJson = JSON.parse(require('fs').readFileSync('./mock/getList.json')); //引入mock好的json資料 getList.mockResolvedValue(Promise.resolve(listJson)); //模擬promise返回 getList().then(res => { expect(res).toEqual(listJson); })
說了這麼多,那為什麼要使用單測呢。在看完上面的描述我想大家也是一頭鬱悶,單測有用嗎?答案當然是有。下面舉個例子:
<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)
這時候就會報錯data.name,因為data不一定有值。正確案例如下
<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>
說白了就是讓你的程式碼邏輯更符合預期結果。
目前在vue中用到的一些基本知識都已經總結完了,如果以後在工作中使用了新的api,時間充裕的情況下我會持續更新。以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45