微信小程序的单元测试miniprogram-simulate 和 Jest

1,917 阅读1分钟

Jest需要创建__test__文件夹,默认会执行该文件夹中的单测代码

组件的单测比较简单,我们直接用miniprogram-simulate提供的方法即可:

const simulate = require('miniprogram-simulate')
 const path = require('path')
 
 function testHandler(desc, fn) {
   test(desc, () => {
     try {
       fn()
       console.log(`${desc} 执行结果:通过`)
     } catch (e) {
       console.log(`${desc} 执行结果:未通过 ${e}`)
     }
   })
 }
 
 function expectHandler(actual) {
   const id = simulate.load(path.join(__dirname, '../../src/component/add-tip/index'))
   const comp = simulate.render(id)
   const parent = document.createElement('parent-wrapper')
   comp.attach(parent)
   // const view = comp.querySelector('.add-tip') 
   const that = comp.instance
   logic(that.data.isShow).toBe(!actual)  // 断言组件isShow的初始值
   that.store = { setItem: jest.fn() };   // jest.fn()的作用 捕获函数的调用和结果 已经this指向 和执行顺序
   // console.log(that.store.setItem.mock)
   that.close()                           // 调用组件的close方法
   logic(that.data.isShow).toBe(actual)   // 断言方法执行后的isShow变量值
 }
 
 function logic(result) {
   return {
     toBe: function (actual) {
       if (result !== actual) {
         throw Error(`当前值不符合预期值, 预期是${actual},结果是 ${result}`)
       }
     }
   }
 }
 
 testHandler('add-tip组件isShow变量', () => expectHandler(false))

由于小程序页面的构成包含Page和生命钩子等miniprogram-simulate不提供的能力,所以我们需要自己先进行全局配置Page:

export const noop = () => {};
export const isFn = fn => typeof fn === 'function';
let wId = 0;
global.Page = ({ data, ...rest }) => {
  const page = {
    data,
    setData: jest.fn(function (newData, cb) {
      this.data = {
        ...this.data,
        ...newData,
      };

      cb && cb();
    }),
    onLoad: noop,
    onReady: noop,
    onUnLoad: noop,
    __wxWebviewId__: wId++,
    ...rest,
  };
  global.wxPageInstance = page;
  return page;
};

global.getApp = function () {
  return {
    baseUrl: 'https://m.maizuo.com/v4/api',
  };
};
global.Date.now = jest.fn(() => 1536708613825);
global.wx = {
  showLoading: jest.fn(),
  hideLoading: jest.fn(),
  showModal: jest.fn(),
  request: jest.fn(),
  getStorageSync: jest.fn(),
  showShareMenu: jest.fn(),
};

module.exports = global;

之后在进行页面级别单测的开发:

import global from '../../wx.js'
import '../../src/subPages/redPacket/redPacketDetail'
import api from '../../src/http/api'
import { post } from '../../src/http/request'

const page = global.wxPageInstance

describe('红包明细页', () => {
  describe('onLoad', () => {
    beforeAll(() => {
      page.api =  api
      page.post = post
      jest.spyOn(page, 'initPage')
      jest.spyOn(page, 'getDayName')
      page.onLoad();
    });

    it('should getDayName', (done) => {
      // expect.assertions(1)
      expect(page.getDayName('2021-06-23 10:37:20')).toEqual('今天')
      done()
    })

    // it('should initPage', (done) =>{
    //   const params = {
    //     page_index: 1,
    //     page_size: 20      
    //   }
    //   page.initPage(params)
    //   console.log(page.data)
    //   expect(page.data.newList[0].readable_business).toEqual('提现');
    //   done()
    // })
  })
})

对复杂项目页面进行单测,还是有点麻烦,很多业务接口做了防注入,不太好进行单测。