详解关于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 拼图游戏 面向对象,注释完整。
Jun 18 Javascript
兼容IE和FF的js脚本代码小结(比较常用)
Dec 06 Javascript
jQuery中:hidden选择器用法实例
Dec 30 Javascript
javascript实现淘宝幻灯片广告展示效果
Apr 27 Javascript
基于原生js淡入淡出函数封装(兼容IE)
Oct 20 Javascript
Bootstrap学习笔记之环境配置(1)
Dec 07 Javascript
JS中去掉array中重复元素的方法
May 26 Javascript
详解超简单的react服务器渲染(ssr)入坑指南
Feb 28 Javascript
VueJS 取得 URL 参数值的方法
Jul 19 Javascript
JavaScript实现PC端四格密码输入框功能
Feb 19 Javascript
解决vue.js中settimeout遇到的问题(时间参数短效果不稳定)
Jul 21 Javascript
js+canvas绘制图形验证码
Sep 21 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
Zend studio for eclipse中使php可以调用mysql相关函数的设置方法
2008/10/13 PHP
php字符串函数学习之strstr()
2015/03/27 PHP
PHP MVC框架路由学习笔记
2016/03/02 PHP
PHP使用DOM和simplexml读取xml文档的方法示例
2017/02/08 PHP
PHP字符串中抽取子串操作实例分析
2019/06/22 PHP
纯CSS3实现质感细腻丝滑按钮
2021/03/09 HTML / CSS
Extjs列表详细信息窗口新建后自动加载解决方法
2010/04/02 Javascript
JS正则表达式获取分组内容的方法详解
2013/11/15 Javascript
父节点获取子节点的字符串示例代码
2014/02/26 Javascript
JavaScript中实现单体模式分享
2015/01/29 Javascript
JavaScript实现表格点击排序的方法
2015/05/11 Javascript
js对象实例详解(JavaScript对象深度剖析,深度理解js对象)
2017/09/21 Javascript
vue实现图书管理demo详解
2017/10/17 Javascript
jQuery解析json格式数据示例
2018/09/01 jQuery
vue实现简单的星级评分组件源码
2018/11/16 Javascript
基于vue.js实现分页查询功能
2018/12/29 Javascript
微信小程序云开发如何使用云函数生成二维码
2019/05/18 Javascript
javaScript把其它类型转换为Number类型
2019/10/13 Javascript
微信小程序绑定手机号获取验证码功能
2019/10/22 Javascript
python实现定制交互式命令行的方法
2014/07/03 Python
Python中使用SAX解析xml实例
2014/11/21 Python
老生常谈python函数参数的区别(必看篇)
2017/05/29 Python
python中with用法讲解
2020/02/07 Python
Python关于__name__属性的含义和作用详解
2020/02/19 Python
django models里数据表插入数据id自增操作
2020/07/15 Python
Python 保存加载mat格式文件的示例代码
2020/08/04 Python
CSS3 重置iphone浏览器按钮input,select等表单元素的默认样式
2014/10/11 HTML / CSS
HTML5页面直接调用百度地图API获取当前位置直接导航目的地的实现代码
2018/03/02 HTML / CSS
详解HTML5 Canvas标签及基本使用
2020/01/10 HTML / CSS
国贸类专业毕业生的求职信分享
2013/12/08 职场文书
服装电子商务创业计划书
2014/01/30 职场文书
劳动竞赛活动总结
2014/05/05 职场文书
安全责任书怎么写
2014/07/28 职场文书
高中生学习计划书
2014/09/15 职场文书
《堡垒之夜》联动《刺客信条》 4月7日正式上线
2022/04/06 其他游戏