Jest 如何 mock localStorage

在撰寫測試經常會需要 mock window class 的操作,例如預期呼叫 alert 啦,呼叫 localstorage 等,那麼為何只是說要呼叫呢? 因為很多時候要測試的是有沒有預期的執行,而不是執行過後的結果是什麼,例如 alert 期望他被呼叫到,而結果是啥並不重要

Jest 如何 mock localStorage
Photo by Sammy Williams / Unsplash

在撰寫測試經常會需要 mock window class 的操作,例如預期呼叫 alert 啦,呼叫 localstorage 等,那麼為何只是說要呼叫呢?
因為很多時候要測試的是有沒有預期的執行,而不是執行過後的結果是什麼,例如 alert 期望他被呼叫到,而結果是啥並不重要,這算是寫測試到現在的一些心得吧XD

那麼這次在 mock window 內的 localStorage 卡了一下,後來終於找到了方法讓測試 mock 成功。

範例

那麼這次要測試的情境是,我寫了一個 class 他會去呼叫 localStorageremoveItemclear 這兩個函式,他們只要被呼叫就好了,至於結果如何,瀏覽器早就幫我們測試好了。

describe('mock localStorage', () => {
  beforeEach(() => {
    const localStorageMock = {
      removeItem: jest.fn(),
      clear: jest.fn()
    }

    Object.defineProperty(window, 'localStorage', { value: localStorageMock })
  })

  afterEach(() => {
    jest.clearAllMocks()
  })
  
  it('should call localStorage clear', () => {
    // ...
    
    expect(localStorage.clear).toHaveBeenCalled()
  })
})

這邊使用了 Object.defineProperty 去複寫 window 內的 localStorage 變成我們自己 mock 的物件,變且已經寫好了 jest.fn() 所以當 localStorageMock.clear 被呼叫就會如我們測試的預期了。