單元測試 - 測試場景記錄

Shapeying發表於2022-02-23

記錄在進行單元測試中所遇到的特殊場景,使用的依賴版本為 "jest": "26.6.0"。不斷補充,積少成多(但願吧···)

模擬 DOM 事件

這裡以模擬touch事件為例。測試中需要模擬左滑右滑,需要觸發 touchstarttouchmove 等事件。

使用 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)
  })
})

相關文章