详解关于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 相关文章推荐
基于jquery的跟随屏幕滚动代码
Jul 24 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
Jul 09 Javascript
jquery validate在ie8下的bug解决方法
Nov 13 Javascript
js事件监听机制(事件捕获)总结
Aug 08 Javascript
JavaScript中关联原型链属性特性
Feb 13 Javascript
分分钟玩转Vue.js组件
Oct 25 Javascript
利用jQuery插件imgAreaSelect实现获得选择域的图像信息
Dec 02 Javascript
Bootstrap基本组件学习笔记之缩略图(13)
Dec 08 Javascript
$.browser.msie 为空或不是对象问题的多种解决方法
Mar 19 Javascript
解决vue打包之后静态资源图片失效的问题
Feb 21 Javascript
javascript canvas实现简易时钟例子
Sep 05 Javascript
vue实现列表拖拽排序的示例代码
Apr 08 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
PHP自定义大小验证码的方法详解
2013/06/07 PHP
深入file_get_contents函数抓取内容失败的原因分析
2013/06/25 PHP
mantis安装、配置和使用中的问题小结
2014/07/14 PHP
Yii中CGridView关联表搜索排序方法实例详解
2014/12/03 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
2018/08/21 PHP
js substr、substring和slice使用说明小记
2011/09/15 Javascript
javascript学习笔记(三) String 字符串类型介绍
2012/06/19 Javascript
js 一个关于图片onload加载的事
2013/11/10 Javascript
JS继承用法实例分析
2015/02/05 Javascript
JavaScript中String.prototype用法实例
2015/05/20 Javascript
jQuery仿360导航页图标拖动排序效果代码分享
2015/08/24 Javascript
AngularJS基础 ng-submit 指令简单示例
2016/08/03 Javascript
vue-awesome-swiper 基于vue实现h5滑动翻页效果【推荐】
2018/11/08 Javascript
七行JSON代码把你的网站变成移动应用过程详解
2019/07/09 Javascript
详解package.json版本号规则
2019/08/01 Javascript
微信小程序wx.request的简单封装
2019/11/13 Javascript
详解Python中的__new__()方法的使用
2015/04/09 Python
Python字符串格式化
2015/06/15 Python
举例讲解Python编程中对线程锁的使用
2016/07/12 Python
PyQt5每天必学之工具提示功能
2018/04/19 Python
Python 统计字数的思路详解
2018/05/08 Python
解决python爬虫中有中文的url问题
2018/05/11 Python
详解python实现小波变换的一个简单例子
2019/07/18 Python
IDLE下Python文件编辑和运行操作
2020/04/25 Python
TensorFlow keras卷积神经网络 添加L2正则化方式
2020/05/22 Python
PHP基于phpqrcode类库生成二维码过程解析
2020/05/28 Python
解决python中import文件夹下面py文件报错问题
2020/06/01 Python
美国马匹用品和马钉购物网站:State Line Tack
2018/08/05 全球购物
档案接收函
2014/01/13 职场文书
《赵州桥》教学反思
2014/02/17 职场文书
十八大标语口号
2014/10/09 职场文书
街道党风廉政建设调研报告
2015/01/01 职场文书
同意报考公务员证明
2015/06/17 职场文书
党员转正大会主持词
2015/07/02 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书
详解JAVA中的OPTIONAL
2021/06/14 Java/Android