小程序的測試和web應用測試區別不大,能夠利用jest進行測試,可是因爲jest只提供了nodejs和瀏覽器執行環境,所以小程序的api咱們須要mock,下面講解小程序測試的一些mock技巧。node
咱們測試小程序時,常常會調用微信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 });
});
},
});
複製代碼
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日');
}));
});
});
複製代碼