详解关于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 相关文章推荐
javascript脚本编程解决考试分数统计问题
Oct 18 Javascript
学习ExtJS TextField常用方法
Oct 07 Javascript
jquery右下角弹出提示框示例代码
Oct 08 Javascript
用javascript删除当前行,添加行(示例代码)
Nov 25 Javascript
Javascript基础教程之数据类型转换
Jan 18 Javascript
JQuery操作textarea,input,select,checkbox方法
Sep 02 Javascript
理解javascript函数式编程中的闭包(closure)
Mar 08 Javascript
BootStrap Table对前台页面表格的支持实例讲解
Dec 22 Javascript
jQuery实现圣诞节礼物动画案例解析
Dec 25 Javascript
ionic3 懒加载
Aug 16 Javascript
如何从零开始利用js手写一个Promise库详解
Apr 19 Javascript
Typescript3.9 常用新特性一览(推荐)
May 14 Javascript
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
php 安全过滤函数代码
2011/05/07 PHP
PHP上传文件参考配置大文件上传
2015/12/16 PHP
PHP实现二维数组中的查找算法小结
2018/06/09 PHP
PDO::beginTransaction讲解
2019/01/27 PHP
js的写法基础分析
2011/01/17 Javascript
基于JQuery实现CheckBox全选全不选
2011/06/27 Javascript
JQuery伸缩导航练习示例
2013/11/13 Javascript
javascipt匹配单行和多行注释的正则表达式
2013/11/20 Javascript
jquery form表单序列化为对象的示例代码
2014/03/05 Javascript
javascript继承的六大模式小结
2015/04/13 Javascript
表单验证插件Validation应用的实例讲解
2015/10/10 Javascript
EasyUI创建人员树的实例代码
2017/09/15 Javascript
使用html+js+css 实现页面轮播图效果(实例讲解)
2017/09/21 Javascript
详解vue组件开发脚手架
2018/06/15 Javascript
详解javascript对数组和json数组的操作
2019/04/15 Javascript
微信小程序一周时间表功能实现
2019/10/17 Javascript
javascript设计模式 ? 备忘录模式原理与用法实例分析
2020/04/21 Javascript
[44:40]KG vs LGD 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python实现抓取城市的PM2.5浓度和排名
2015/03/19 Python
python过滤字符串中不属于指定集合中字符的类实例
2015/06/30 Python
Python中防止sql注入的方法详解
2017/02/25 Python
python3 pathlib库Path类方法总结
2019/12/26 Python
Python爬虫入门教程02之笔趣阁小说爬取
2021/01/24 Python
喜诗官方在线巧克力店:See’s Candies
2017/01/01 全球购物
澳洲Chemist Direct药房中文网:澳洲大型线上直邮药房
2019/11/04 全球购物
社区工作者思想汇报
2014/01/13 职场文书
技校毕业生个人学习的自我评价
2014/02/21 职场文书
小露珠教学反思
2014/04/30 职场文书
结对共建工作方案
2014/06/02 职场文书
小学生美德少年事迹材料
2014/08/24 职场文书
2014大四本科生自我鉴定总结
2014/10/04 职场文书
私人房屋买卖协议书
2014/10/04 职场文书
2014村党支部书记党建工作汇报材料
2014/11/02 职场文书
2015年助理政工师工作总结
2015/05/26 职场文书
详解Python常用的魔法方法
2021/06/03 Python
人工智能深度学习OpenAI baselines的使用方法
2022/05/20 Python