详解关于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函数中onmousedown和onclick的区别和联系探讨
May 19 Javascript
javascript常见数据验证插件大全
Aug 03 Javascript
jQuery实现Email邮箱地址自动补全功能代码
Nov 03 Javascript
js中使用使用原型(prototype)定义方法的好处详解
Jul 04 Javascript
基于JS如何实现给字符加千分符(65,541,694,158)
Aug 03 Javascript
jQuery插件ajaxFileUpload使用详解
Jan 10 Javascript
jquery 实时监听输入框值变化的完美方法(必看)
Jan 26 Javascript
Node.js 异步异常的处理与domain模块解析
May 10 Javascript
js实现音乐播放控制条
Sep 09 Javascript
js实现1,2,3,5数字按照概率生成
Sep 12 Javascript
vue created钩子函数与mounted钩子函数的用法区别
Nov 05 Javascript
js异步接口并发数量控制的方法示例
Nov 22 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.ini中文版
2006/10/09 PHP
PHP安全的URL字符串base64编码和解码
2014/06/19 PHP
php模拟登陆的实现方法分析
2015/01/09 PHP
10款PHP开源商城系统汇总介绍
2015/07/23 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
2016/08/19 PHP
Mac下php 5升级到php 7的步骤详解
2017/04/26 PHP
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
javascript 日期时间函数(经典+完善+实用)
2009/05/27 Javascript
早该知道的7个JavaScript技巧
2013/03/27 Javascript
JavaScript表单通过正则表达式验证电话号码
2014/03/14 Javascript
使用js画图之饼图
2015/01/12 Javascript
理解javascript中的Function.prototype.bind的方法
2017/02/03 Javascript
微信小程序“摇一摇”的实例代码
2017/07/20 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
angularjs获取到My97DatePicker选中的值方法
2018/10/02 Javascript
vue中移动端调取本地的复制的文本方式
2020/07/18 Javascript
Vue 根据条件判断van-tab的显示方式
2020/08/03 Javascript
Python中的高级函数map/reduce使用实例
2015/04/13 Python
自己使用总结Python程序代码片段
2015/06/02 Python
Python实现数据库编程方法详解
2015/06/09 Python
Python 查看文件的读写权限方法
2018/01/23 Python
Python实现屏幕截图的两种方式
2018/02/05 Python
Python + Flask 实现简单的验证码系统
2019/10/01 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
python调用接口的4种方式代码实例
2019/11/19 Python
python3 requests库实现多图片爬取教程
2019/12/18 Python
python如何进行矩阵运算
2020/06/05 Python
Python延迟绑定问题原理及解决方案
2020/08/04 Python
Python自动化之UnitTest框架实战记录
2020/09/08 Python
孕妇内衣和胸罩:Cake Maternity
2018/07/16 全球购物
Hotels.com泰国:酒店预订网站
2019/11/20 全球购物
财务部副经理岗位职责
2014/03/14 职场文书
共产党员公开承诺书
2014/03/25 职场文书
水利局群众路线专题民主生活会发言材料
2014/09/21 职场文书
先进工作者个人总结
2015/02/15 职场文书
教师自荐信范文
2015/03/06 职场文书