详解关于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 instanceof 的使用方法示例介绍
Oct 23 Javascript
javascript右下角弹层及自动隐藏(自己编写)
Nov 20 Javascript
jQuery实现鼠标经过图片预览大图效果
Apr 10 Javascript
在myeclipse中如何加入jquery代码提示功能
Jun 03 Javascript
jquery动态改变div宽度和高度
Feb 09 Javascript
JS实现弹性菜单效果代码
Sep 07 Javascript
jquery按回车键实现表单提交的简单实例
May 25 Javascript
下一代Bootstrap的5个特点 超酷炫!
Jun 17 Javascript
JavaScript的数据类型转换原则(干货)
Mar 15 Javascript
探秘vue-rx 2.0(推荐)
Sep 21 Javascript
使用vue重构资讯页面的实例代码解析
Nov 26 Javascript
一看就会的vuex实现登录验证(附案例)
Jan 09 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程序级守护进程的实现与优化的使用概述
2013/05/02 PHP
如何使用php脚本给html中引用的js和css路径打上版本号
2015/11/18 PHP
PHP中addcslashes与stripcslashes函数用法分析
2016/01/07 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
简单三步,搞掂内存泄漏
2007/03/10 Javascript
『jQuery』.html(),.text()和.val()的概述及使用
2013/04/22 Javascript
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
点击表单提交时出现jQuery没有权限的解决方法
2014/07/23 Javascript
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
2014/09/26 NodeJs
JQuery实现展开关闭层的方法
2015/02/17 Javascript
JavaScript中的依赖注入详解
2015/03/18 Javascript
jQuery解决input超多的表单提交
2015/08/10 Javascript
js倒计时抢购实例
2015/12/20 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
2017/07/11 Javascript
React中使用UEditor百度富文本的方法
2018/08/22 Javascript
VUE.js实现动态设置输入框disabled属性
2019/10/28 Javascript
微信小程序登陆注册功能的实现代码
2019/12/10 Javascript
[00:48]DOTA2国际邀请赛公开赛报名开始 扫码开启逐梦之旅
2018/06/06 DOTA
Python函数学习笔记
2008/10/07 Python
python转换字符串为摩尔斯电码的方法
2015/07/06 Python
深入解析Python中的lambda表达式的用法
2015/08/28 Python
实例解析Python的Twisted框架中Deferred对象的用法
2016/05/25 Python
浅析python打包工具distutils、setuptools
2018/04/20 Python
tensorflow实现逻辑回归模型
2018/09/08 Python
Django实现单用户登录的方法示例
2019/03/28 Python
解决Jupyter无法导入已安装的 module问题
2020/04/17 Python
Python爬取你好李焕英豆瓣短评生成词云的示例代码
2021/02/24 Python
HTML5中Localstorage的使用教程
2015/07/09 HTML / CSS
航海技术专业毕业生推荐信
2014/07/09 职场文书
入党群众意见范文
2015/06/02 职场文书
爱国主义电影观后感
2015/06/18 职场文书
2016应届毕业生实习评语
2015/12/01 职场文书
python基础之类方法和静态方法
2021/10/24 Python
MongoDB误操作后使用oplog恢复数据
2022/04/11 MongoDB
mysql实现将字符串字段转为数字排序或比大小
2022/06/14 MySQL