详解关于Vue单元测试的几个坑


Posted in Javascript onApril 26, 2020

一、写在前面

这篇文章的代码使用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", 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);
 });

先说为什么需要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单元测试 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js传值 判断
Oct 26 Javascript
在Javascript中定义对象类别
Dec 22 Javascript
利用javascript移动div层-javascript 拖动层
Mar 22 Javascript
js注意img图片的onerror事件的分析
Jan 01 Javascript
浅析onsubmit校验表单时利用ajax的return false无效问题
Jul 10 Javascript
使用jsonp完美解决跨域问题
Nov 27 Javascript
JavaScript常用脚本汇总(三)
Mar 04 Javascript
js实现鼠标移到链接文字弹出一个提示层的方法
May 11 Javascript
js 上传文件预览的简单实例
Aug 16 Javascript
使用vue根据状态添加列表数据和删除列表数据的实例
Sep 29 Javascript
最简单的JS实现json转csv的方法
Jan 10 Javascript
一篇文章告诉你如何实现Vue前端分页和后端分页
Feb 18 Vue.js
es6函数之箭头函数用法实例详解
Apr 25 #Javascript
es6数组之扩展运算符操作实例分析
Apr 25 #Javascript
es6函数之尾调用优化实例分析
Apr 25 #Javascript
es6函数之尾递归用法实例分析
Apr 25 #Javascript
javascript 易错知识点实例小结
Apr 25 #Javascript
javascript执行上下文、变量对象实例分析
Apr 25 #Javascript
JavaScript ECMA-262-3 深入解析(二):变量对象实例详解
Apr 25 #Javascript
You might like
简单实现限定phpmyadmin访问ip的方法
2013/03/05 PHP
手把手教你打印出PDF(关于fpdf的简单应用)
2013/06/25 PHP
PHP实现中文圆形印章特效
2015/06/19 PHP
详解js异步文件加载器
2016/01/24 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
用JQuery 实现AJAX加载XML并解析的脚本
2009/07/25 Javascript
javascript学习笔记(十四) window对象使用介绍
2012/06/20 Javascript
js实现按钮加背景图片常用方法
2014/11/01 Javascript
Jquery树插件zTree用法入门教程
2015/02/17 Javascript
在Node.js应用中读写Redis数据库的简单方法
2015/06/30 Javascript
使用jspdf生成pdf报表
2015/07/03 Javascript
javascript实现简单查找与替换的方法
2015/07/22 Javascript
Easyui Treegrid改变默认图标的方法
2016/04/29 Javascript
javascript实现的上下无缝滚动效果
2016/09/19 Javascript
谈谈第三方App接入微信登录 解读
2016/12/27 Javascript
微信小程序实现图片预加载组件
2017/01/18 Javascript
详解用Node.js写一个简单的命令行工具
2018/03/01 Javascript
详解KOA2如何手写中间件(装饰器模式)
2018/10/11 Javascript
vue实现自定义H5视频播放器的方法步骤
2019/07/01 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
2019/12/12 Javascript
js Math数学简单使用操作示例
2020/03/13 Javascript
vue 中的动态传参和query传参操作
2020/11/09 Javascript
浅析vue中的nextTick
2020/12/28 Vue.js
Python中使用__new__实现单例模式并解析
2019/06/25 Python
python能做什么 python的含义
2019/10/12 Python
非常震撼的纯CSS3人物行走动画
2016/02/24 HTML / CSS
使用Html5 Stream开发实时监控系统
2020/06/02 HTML / CSS
英国定做窗帘和纺织品面料一站式商店:Dekoria
2018/08/29 全球购物
《果园机器人》教学反思
2014/04/13 职场文书
外语专业毕业生自荐信
2014/04/14 职场文书
幼儿园大班开学寄语
2014/08/02 职场文书
我的大学四年规划书范文2014
2014/09/26 职场文书
小学教师师德培训心得体会
2016/01/09 职场文书
开学第一周日记(三篇范文)
2019/08/23 职场文书
数据库连接池
2021/04/06 MySQL
Pandas实现DataFrame的简单运算、统计与排序
2022/03/31 Python