小程序單元測試

小程序的測試和web應用測試區別不大,能夠利用jest進行測試,可是因爲jest只提供了nodejs和瀏覽器執行環境,所以小程序的api咱們須要mock,下面講解小程序測試的一些mock技巧。node

mock小程序API

咱們測試小程序時,常常會調用微信api,例如wx.showLoading方法,可是由於咱們的執行環境未定義該方法,會出現調用錯誤。git

咱們能夠經過jest提供的global設置全局變量,能夠在測試文件中單獨編寫,或者在package.json的jest塊設置setupFiles屬性,讓jest自動加載。github

"jest": {
    "setupFiles": ["./__tests__/wx.js"]
  },
複製代碼

./tests/wx.js文件內容以下,表示將小程序的api方法定義爲mock方法。web

global.wx = {
  showLoading: jest.fn(),
  hideLoading: jest.fn(),
  showModal: jest.fn(),
  request: jest.fn(),
  getStorageSync: jest.fn(),
  showShareMenu: jest.fn(),
};
複製代碼

測試小程序頁面

// 空白的小程序頁面代碼
Page({
 onLoad () {
    // your code
 }
})
複製代碼

一個空白的小程序頁面,代碼會被Page方法包裹,同時Page初始化後,會執行onLoad、onReady等生命週期方法,並且當前對象還能調用setData方法對頁面data數據進行修改。json

咱們須要mock 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;
};
複製代碼

舉個例子

假設咱們的小程序頁面是一個電影列表展現,業務代碼以下。api

const filmServer = require('../../server/film.js');

Page({
  data: {
    comingFilms: [],
  },
  onLoad() {
    this.getComingFilm();
  },
  // 獲取即將上映電影列表
  getComingFilm() {
    return filmServer.getComingSoon(1, 5).then((data) => {
      data.films.forEach((film) => {
        const displayDate = `${new Date(film.premiereAt).getMonth() + 1}${new Date(film.premiereAt).getDate()}日`;
        film.displayDate = displayDate;
      });
      this.setData({ comingFilms: data.films });
    });
  },
});

複製代碼

咱們的編寫兩個測試用例保證代碼的正確運行。

一、保證onLoad時執行getComingFilm方法。

二、保證getComingFilm後日期數據進行格式化。

import '../../pages/film'; // 加載須要測試的頁面

// 獲取當前初始化的page對象,後續可用來調用setData等方法,相似小程序頁面裏的this。
const page = global.wxPageInstance;
// mock網絡請求
jest.mock('../../server/film.js');

describe('電影首頁', () => {
  describe('onLoad', () => {
    beforeAll(() => {
      // spyOn後可以使方法具備mock屬性,同時不影響方法調用。
      jest.spyOn(page, 'getComingFilm');
      // 執行頁面onLoad生命週期。
      page.onLoad();
    });
    it('should getComingFilm', () => {
      // 斷言onLoad後,是否執行了getComingFilm方法。由於咱們前面已經將getComingFilm進行spyOn了,因此能夠執行toBeCalled判斷,不然會出錯。
      expect(page.getComingFilm).toBeCalled();
    });
  });
  describe('getComingFilm', () => {
    it('should format premiereAt as MM月DD日 ', () => page.getComingFilm().then(() => {
        // 斷言獲取數據後,原始數據增長displayDate屬性,格式化爲MM月DD日
        expect(page.data.comingFilms[0].displayDate).toEqual('9月12日');
      }));
  });
});

複製代碼

🌟🌟因爲測試代碼比較長,上面只截取了部分,完整代碼能夠訪問github獲取

相關文章
相關標籤/搜索