详解关于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 相关文章推荐
IE下window.onresize 多次调用与死循环bug处理方法介绍
Nov 12 Javascript
javascript修改表格背景色实例代码分享
Dec 10 Javascript
Javascript玩转继承(三)
May 08 Javascript
jQuery实现在textarea指定位置插入字符或表情的方法
Mar 11 Javascript
Javascript中的匿名函数与封装介绍
Mar 15 Javascript
jQuery原理系列-css选择器的简单实现
Jun 07 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
Feb 22 Javascript
Ajax实现不刷新取最新商品
Mar 01 Javascript
基于JavaScript实现移动端无限加载分页
Mar 27 Javascript
ExtJs整合Echarts的示例代码
Feb 27 Javascript
Vue 中对图片地址进行拼接的方法
Sep 03 Javascript
详解ES6系列之私有变量的实现
Nov 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
DC动漫人物排行
2020/03/03 欧美动漫
来自phpguru得Php Cache类源码
2010/04/15 PHP
PHP基础学习小结
2011/04/17 PHP
php表单敏感字符过滤类
2014/12/08 PHP
javascript中字符串替换函数replace()方法与c# 、vb 替换有一点不同
2010/06/25 Javascript
关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
2010/10/14 Javascript
jQuery源码分析-01总体架构分析
2011/11/14 Javascript
使用jquery动态加载js文件的方法
2014/12/24 Javascript
jQuery on()方法绑定动态元素的点击事件无响应的解决办法
2016/07/07 Javascript
jQuery Ztree行政地区树状展示(点击加载)
2016/11/09 Javascript
最通俗易懂的javascript变量提升详解
2017/08/05 Javascript
JavaScript实现图片切换效果
2017/08/12 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
在ES5与ES6环境下处理函数默认参数的实现方法
2018/05/13 Javascript
vue2.0父子组件间传递数据的方法
2018/08/16 Javascript
vue 2.8.2版本配置刚进入时候的默认页面方法
2018/09/21 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
JavaScript实现Excel表格效果
2020/02/07 Javascript
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
python操作数据库之sqlite3打开数据库、删除、修改示例
2014/03/13 Python
使用Python脚本操作MongoDB的教程
2015/04/16 Python
使用Python的Tornado框架实现一个一对一聊天的程序
2015/04/25 Python
Python 爬虫学习笔记之多线程爬虫
2016/09/21 Python
使用Python对Access读写操作
2017/03/30 Python
在windows下Python打印彩色字体的方法
2018/05/15 Python
Python生成短uuid的方法实例详解
2018/05/29 Python
Pycharm无法显示动态图片的解决方法
2018/10/28 Python
python同时替换多个字符串方法示例
2019/09/17 Python
浅析canvas元素的html尺寸和css尺寸对元素视觉的影响
2019/07/22 HTML / CSS
Superdry极度干燥美国官网:英国制造的服装品牌
2018/11/13 全球购物
酒店销售主管岗位职责
2014/01/04 职场文书
放飞蜻蜓反思
2014/02/05 职场文书
《姥姥的剪纸》教学反思
2014/02/25 职场文书
竞选体育委员演讲稿
2014/04/26 职场文书
暑期家教宣传单
2015/07/14 职场文书
解决python存数据库速度太慢的问题
2021/04/23 Python