- A+
所属分类:Web前端
记录在进行单元测试中所遇到的特殊场景,使用的依赖版本为 "jest": "26.6.0"
。不断补充,积少成多(但愿吧···)
模拟 DOM 事件
这里以模拟touch
事件为例。测试中需要模拟左滑和右滑,需要触发 touchstart
和 touchmove
等事件。
使用 dispatchEvent(event: Event)
describe('TouchLREvent', () => { // 目标元素 let demoDom: HTMLElement | null = null; beforeAll(() => { // 创建并添加目标元素到body下 demoDom = document.createElement('div') demoDom.style.height = '500px' demoDom.style.width = '300px' document.body.appendChild(demoDom) }) afterAll( () => { // 清除元素 document.body.removeChild(demoDom!) demoDom = null }) test('left' , () => { // 模拟回调函数 let leftCallBack = jest.fn() let rightCallBack = jest.fn() TouchLREvent(demoDom!,leftCallBack,rightCallBack) // 模拟 touchstart demoDom?.dispatchEvent(new TouchEvent('touchstart',{ touches: [ // @ts-ignore {clientX: 100,clientY:100} ] })) // 模拟 touchmove demoDom?.dispatchEvent(new TouchEvent('touchmove',{ touches: [ // @ts-ignore {clientX: 60,clientY:100} ] })) // 模拟 touchend demoDom?.dispatchEvent(new TouchEvent('touchend',{ touches: [ // @ts-ignore {clientX: 50,clientY:100} ] })) expect(leftCallBack).toBeCalled() expect(rightCallBack).toBeCalledTimes(0) // 还原函数 leftCallBack.mockRestore() rightCallBack.mockRestore() }) })
模拟 localStorage
在window
下自己定义一个localStorage
对象。
模拟的localStorage
对象实现如下:
// localStorage功能的简易实现 export default class LocalStorageMock { private store: Record<string, string> = {}; public setItem(key: string, value: string) { this.store[key] = String(value); } public getItem(key: string): string | null { return this.store[key] || null; } public removeItem(key: string) { delete this.store[key]; } public clear() { this.store = {}; } public key(index: number): string | null { return Object.keys(this.store)[index] || null; } public get length(): number { return Object.keys(this.store).length; } }
测试文件:
import LocalStorageMock from './__mock__/localStorage' describe('test LocalStorage', () => { const localStorageMock = new LocalStorageMock() const _data = {test:123,test1:'456',test2:true,test3:{}} beforeAll(() => { // 自定义 localStorage 对象 Object.defineProperty(window, 'localStorage', { value: localStorageMock }); }) afterAll( () => { // 环境还原 // @ts-ignore delete window.localStorage }) test('set same data',() => { LocalStorage.setItem('test',_data) expect(LocalStorage.getItem('test')).toEqual(_data) }) })
当然,如果多个测试文件都需要localStorage
,可以在全局模拟此对象,在setupFiles
中实现即可。
模拟 location
delete window.location
, 然后重新赋值
describe('test getSearchs', () => { // 备份 location对象 const { location } = window beforeAll( () => { // 删除 location // @ts-ignore delete window.location; }) afterAll( () => { // 还原 location window.location = location }) test('one search params, no hash', () => { // 测试时 模拟location // @ts-ignore window.location = new URL('https://www.baidu.com/?test=123') expect(getSearchs()).toEqual({test:"123"}) }) })
模拟 userAgent
思路和 模拟 location
一样,先删除再赋值
describe('test getStatuBarHeight', () => { // 备份 const { navigator } = window beforeAll( () => { // 模拟 //@ts-ignore delete window.navigator }) afterAll( () => { // 还原 window.navigator = navigator }) test('no xx in userAgent', () => { // 模拟 userAgent window.navigator = { ...navigator, userAgent:'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1' } expect(xx).toBe(xx) }) })