欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

从零开始的小程序单元测试实践(附有避免陷阱和源代码跟踪指南)

最编程 2024-04-20 16:49:34
...
  • 针对第1点原因,可以写一下测试代码(components/user.js)
     Component({
         data: {
             nickname: ''
         },
         methods: {
             handleUserInfo: function(e) {
                 console.log(e);
             }
         }
     })
    
  • npm run test,可以看到事件还是成功触发了,不过detail{}
      console.log components/user.js:21
     { type: 'getuserinfo',
       timeStamp: 948,
       target: { id: '', offsetLeft: 0, offsetTop: 0, dataset: {} },
       currentTarget: { id: '', offsetLeft: 0, offsetTop: 0, dataset: {} },
       detail: {},
       touches: {},
       changedTouches: {} }
    
  • 原因1排除,查原因2
  • dispatchEvent方法是被测试组件的子组件被测试组件simulate.render函数返回
  • 浏览node_modules/miniprogram-simulate/src/index.js,看到render函数(152行),可以看到返回的组件由jComponent.create提供
  • 浏览node_modules/j-component/src/index.jscreate函数,可以看到其返回了RootComponent实例,而RootComponent是由./render/component.js提供
  • 浏览node_modules/j-component/src/render/component.jsdispatchEvent函数,在这里可以打下日志测试(本文就不打了,结果是这里的options就是user.spec.js dispatchEvent函数的第二个参数detail是有值的)
  • 继续跟踪源码,由于咱们的是自定义事件,所以会走到91行的代码,该代码块如下:
    // 自定义事件
      const customEvent = new CustomEvent(eventName, options);
    
      // 模拟异步情况
      setTimeout(() => {
        dom.dispatchEvent(customEvent);
    
        exparser.Event.dispatchEvent(customEvent.target, exparser.Event.create(eventName, {}, {
          originalEvent: customEvent,
          bubbles: true,
          capturePhase: true,
          composed: true,
          extraFields: {
            touches: options.touches || {},
            changedTouches: options.changedTouches || {},
          },
        }));
      }, 0);
    
  • 可以看到调用了exparser.Event.dispatchEvent函数,该函数的第二个参数调用了exparser.Event.create对自定义事件进行了包装,这里还没到最底层,需要继续跟踪
  • exparser对象是miniprogram-exparser模块提供的,浏览node_modules/miniprogram-exparser/exparser.min.js,发现该文件被混淆了,不过没关系混淆后的代码逻辑是不变的,只不过变量名变得无意义,可读性变差
  • 使用webstorm格式化该文件,这里我传了一份格式化好的到github wxparser.js,可在线观看
  • 需要在源码中搜索三个参数create函数(Object.create不算),需要有耐心,经过排查后发现168行代码应该是目标代码
    i.create = function(e, t, r) {
        r = r || {};
        var n = r.originalEvent, o = r.extraFields || {}, a = Date.now() - l, s = new i;
        s.currentTarget = null, s.type = e, s.timeStamp = a, s.mark = null, s.detail = t, s.bubbles = !!r.bubbles, s.composed = !!r.composed, s.__originalEvent = n, s.__hasCapture = !!r.capturePhase, s.__stopped = !1, s.__dispatched = !1;
        for (var u in o) s[u] = o[u];
        return s;
    }
    
  • 可以看到s.detail = t这个赋值,tcreate第二个参数,由node_modules/j-component/render/component.jswxparser.Event.create传入,但是传入的第二个参数写死了{},所以咱们的组件获取detail的时候永远为{},将其修改为options.detail||{}即可,修改后代码如下:
    exparser.Event.dispatchEvent(customEvent.target, exparser.Event.create(eventName, options.detail||{}, xxxxxx
    
  • 重新测试
     PASS  tests/components/user.spec.js