详解关于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 indexOf函数使用说明
Jul 03 Javascript
写入cookie的JavaScript代码库 cookieLibrary.js
Oct 24 Javascript
dess中一个简单的多路委托的实现
Jul 20 Javascript
JS字符串累加Array不一定比字符串累加快(根据电脑配置)
May 14 Javascript
document节点对象的获取方式示例介绍
Dec 24 Javascript
js定时调用方法成功后并停止调用示例
Apr 08 Javascript
Node.js异步I/O学习笔记
Nov 04 Javascript
jquery.validate 自定义验证方法及validate相关参数
Jan 18 Javascript
jQuery表单验证简单示例
Oct 17 Javascript
BootStrap select2 动态改变值的方法
Feb 10 Javascript
基于百度地图api清除指定覆盖物(Overlay)的方法
Jan 26 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
Jul 29 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
一个用mysql_odbc和php写的serach数据库程序
2006/10/09 PHP
PHP访问MYSQL数据库封装类(附函数说明)
2010/12/04 PHP
php将文本文件转换csv输出的方法
2014/12/31 PHP
PHP实现批量修改文件后缀名的方法
2015/07/30 PHP
javascript 动态添加表格行
2006/06/22 Javascript
根据地区不同显示时间的javascript代码
2007/08/13 Javascript
javascript 当前日期加(天、周、月、年)
2009/08/09 Javascript
javascript sudoku 数独智力游戏生成代码
2010/03/27 Javascript
javascript中的一些注意事项 更新中
2010/12/06 Javascript
jQuery去掉字符串起始和结尾的空格(多种方法实现)
2013/04/01 Javascript
异步动态加载JS并运行(示例代码)
2013/12/13 Javascript
Javascript 构造函数详解
2014/10/22 Javascript
无需 Flash 使用 jQuery 复制文字到剪贴板
2016/04/26 Javascript
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
jquery实现tab选项卡切换效果(悬停、下方横线动画位移)
2017/05/05 jQuery
H5基于iScroll实现下拉刷新和上拉加载更多
2017/07/18 Javascript
微信小程序实现动态设置placeholder提示文字及按钮选中/取消状态的方法
2017/12/14 Javascript
简单理解Vue中的nextTick方法
2018/01/30 Javascript
Vue弹出菜单功能的实现代码
2018/09/12 Javascript
[45:16]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第一场 12.12
2020/12/16 DOTA
Python中自定义函数的教程
2015/04/27 Python
Python实现返回数组中第i小元素的方法示例
2017/12/04 Python
解决Python pandas df 写入excel 出现的问题
2018/07/04 Python
python pandas移动窗口函数rolling的用法
2020/02/29 Python
Python实现扫码工具的示例代码
2020/10/09 Python
Pandas之缺失数据的实现
2021/01/06 Python
美国排名第一的在线葡萄酒商店:Wine.com
2016/09/07 全球购物
品恩科技软件测试面试题
2014/10/26 面试题
活动总结怎么写啊
2014/05/07 职场文书
电话客服工作职责
2014/07/27 职场文书
先进教师个人总结
2015/02/11 职场文书
销售员自我评价
2015/03/11 职场文书
2015年个人审计工作总结
2015/04/07 职场文书
礼仪培训心得体会
2016/01/22 职场文书
《失物招领》教学反思
2016/02/20 职场文书
MySQL创建定时任务
2022/01/22 MySQL