詳解關於Vue單元測試的幾個坑
一、寫在前面
這篇文章的程式碼使用karma,mocha,chai,sinon-chai配合Vue的例項屬性進行單元測試
二、全域性的元件的坑
由於我的g-icon是全域性註冊的,所以使用g-input元件時的時候g-icon是直接用的,所以測試時有關icon的程式碼永遠是錯的。
把g-icon區域性註冊的元件
三、在測試中觸發點選事件
模擬我在app.vue裡使用g-input元件
<g-input v-model="message"></g-input>
使用new event 和 dispatch 模擬事件在元件上觸發,雖然這個事件和我們實際的事件不一樣,但名字一樣就夠了,測試回撥函式自帶的引數
it("支援事件",() => { ["change","input","focus","blur"].forEach(eventName => { vm = new Constructor({}).$mount(); const callback = sinon.fake(); vm.$on(eventName,callback); let event = new Event(eventName); Object.defineProperty(event,"target",{ value: { value: "hi" },enumerable: true }); let inputElement = vm.$el.querySelector("input"); inputElement.dispatchEvent(event); expect(callback).to.have.been.calledWith("hi"); }); });
測試這個元件事件觸發時,回撥的引數,由於自定義事件沒有target,我們需要自己寫上去
value: { value: "hi" }第一個value是defineProperty的
四、Vue的版本
坑來自於下面一段程式碼
it("接受gutter",function(done) { Vue.component("g-row",Row); Vue.component("g-col",Col); const div = document.createElement("div"); document.body.appendChild(div); div.innerHTML = ` <g-row gutter="20"> <g-col></g-col> <g-col></g-col> </g-row>`; const vm = new Vue({ el: div }); setTimeout(() => { const row = vm.$el.querySelector(".row"); expect(getComputedStyle(row).marginRight).to.eq("-10px"); expect(getComputedStyle(row).marginLeft).to.eq("-10px"); const cols = vm.$el.querySelectorAll(".col"); expect(getComputedStyle(cols[0]).paddingRight).to.eq("10px"); expect(getComputedStyle(cols[1]).paddingLeft).to.eq("10px"); done(); vm.$el.remove(); vm.$destroy(); },0); });
我使用直接在el上寫入template程式碼,所以我預設的import Vue from "vue"(runtimeonly版本)無法編譯這個程式碼,import Vue from "../node_modules/vue/dist/vue.esm.js"使用上面引入即可
在沒有template選項是,el不替換
五、非同步測試
還是這個程式碼,先看以下測試兩個元件關係
it("接受gutter",0); });
先說為什麼需要seTimeout
從created和mounted鉤子說起,createElement和appendChild在js程式碼是同步的,兩個鉤子分別在這兩段程式碼後執行,鉤子非同步執行的。
由於我們在g-row元件中有mounted鉤子,所以我們必須得進行非同步檢測,否則我們在new Vue之後立馬進行測試,鉤子還沒執行完。
mocha非同步測試
mocha預設不執行非同步,加入done引數,呼叫done()就可以
六、垃圾回收
每一個測試完成之後,都要寫下面兩條程式碼
vm.$el.remove(); vm.$destroy();
有兩個作用:
- 銷燬在頁面中的資料
- 銷燬在記憶體的資料
雖然js是單執行緒,但是還有一個dom執行緒
var div = document. getElementById('xxx') div.onclick = function() { ///code } setTimeout(function(){ div. remove() },3000)
現在我們討論,什麼時候div上的函式被回收
函式被全域性變數div上的onlick引用了
div.remove()只是在頁面刪掉了,沒有被記憶體刪掉
var div = document. getElementById('xxx') div.onclick = function() { ///code } setTimeout(function(){ div = mull },3000)
這個函式並沒有被刪除,函式是寫在dom上的,div變數只是引用了dom物件
var div = document. getElementById('xxx') div.onclick = function() { ///code } setTimeout(function(){ var div2 = document. getElementById('xxx') },3000)
div= null和div.remove同時做就可以了,分別從記憶體和dom上刪除了
ie有bug,即使這樣都刪不了,div.onlick = null 可以
到此這篇關於關於Vue單元測試的幾個坑的文章就介紹到這了,更多相關 Vue單元測試 內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!