How to mock localStorage in JavaScript unit tests?

前端 未结 14 1603
南笙
南笙 2020-11-29 18:46

Are there any libraries out there to mock localStorage?

I\'ve been using Sinon.JS for most of my other javascript mocking and have found it is really gr

14条回答
  •  独厮守ぢ
    2020-11-29 19:21

    You don't have to pass the storage object to each method that uses it. Instead, you can use a configuration parameter for any module that touches the storage adapter.

    Your old module

    // hard to test !
    export const someFunction (x) {
      window.localStorage.setItem('foo', x)
    }
    
    // hard to test !
    export const anotherFunction () {
      return window.localStorage.getItem('foo')
    }
    

    Your new module with config "wrapper" function

    export default function (storage) {
      return {
        someFunction (x) {
          storage.setItem('foo', x)
        }
        anotherFunction () {
          storage.getItem('foo')
        }
      }
    }
    

    When you use the module in testing code

    // import mock storage adapater
    const MockStorage = require('./mock-storage')
    
    // create a new mock storage instance
    const mock = new MockStorage()
    
    // pass mock storage instance as configuration argument to your module
    const myModule = require('./my-module')(mock)
    
    // reset before each test
    beforeEach(function() {
      mock.clear()
    })
    
    // your tests
    it('should set foo', function() {
      myModule.someFunction('bar')
      assert.equal(mock.getItem('foo'), 'bar')
    })
    
    it('should get foo', function() {
      mock.setItem('foo', 'bar')
      assert.equal(myModule.anotherFunction(), 'bar')
    })
    

    The MockStorage class might look like this

    export default class MockStorage {
      constructor () {
        this.storage = new Map()
      }
      setItem (key, value) {
        this.storage.set(key, value)
      }
      getItem (key) {
        return this.storage.get(key)
      }
      removeItem (key) {
        this.storage.delete(key)
      }
      clear () {
        this.constructor()
      }
    }
    

    When using your module in production code, instead pass the real localStorage adapter

    const myModule = require('./my-module')(window.localStorage)
    

提交回复
热议问题