How to use localStorage in unit tests with Chai

情到浓时终转凉″ 提交于 2020-01-30 07:57:05

问题


I have an app with react and redux. My test engine is - Chai

In my reducer (src/my_reducer.js), I try to get token from localStorage like this:

const initialState = {
  profile: {},
  token: window.localStorage.getItem('id_token') ? window.localStorage.getItem('id_token') : null,
}

In my tests file (test/reducer_spec.js) I have import 'my_reducer' before test cases:

import myReducer from '../src/my_reducer'

And I have an error, if I try to run test - localStorage (or window.localStorage) - undefined.

I need to mock localStorage? If I need, where is the place for it?


回答1:


I presume you are running your tests with mocha? mocha tests run in node.js, and node.js does not have a global window variable. But you can easily create one in your tests:

global.window = {};

You can even add the localStorage to it immediately:

global.window = { localStorage: /* your mock localStorage */ }

The mock depends on what you store in your local storage, but for the example code above this might be a reasonable mock object:

var mockLocalStorage = {
    getItem: function (key) {
        if( key === 'id_token' ){ return /* a token object */; }
        return null;
    }
}

Of course, for different tests you can have different mocks, e.g. another mock might always return null to test the case that the key cannot be found.




回答2:


I solve problem with mock-local-storage My run test command is:

mocha -r mock-local-storage --compilers js:babel-core/register --recursive



回答3:


For testing purposes I recommend not to make any calls which may have side effects or call external modules in declarations. Because requiring / importing your reducer implicitly calls window.localStorage.getItem(...) clean testing gets hard.

I'd suggest to wrap your initialization code with a init method so nothing happens if you require/import your module before calling init. Then you can use beforeEach afterEach to cleanly setup mocks/sandboxes.

import myReducer from '../src/my_reducer'
describe('with faked localStorage', function() {
  var sandbox

  beforeEach(function() {
    sandbox = sinon.sandbox.create()
    // fake window.localStorage
  })

  afterEach(function() {
    sandbox.restore()
  })

  describe('the reducer', function() {
    before(function() {
      myReducer.init()
    })
  })
})

The second best solution is to postpone the import and use require within the before test hook.

describe('with fake localStorage', function() {
  var sandbox

  beforeEach(function() {
    sandbox = sinon.sandbox.create()
    // fake window.localStorage
  })

  afterEach(function() {
    sandbox.restore()
  })

  describe('the reducer', function() {
    var myReducer

    before(function() {
      myReducer = require('../src/my_reducer')
    })

  })
})



回答4:


It is because you are not running Chai in a browser environment.

Try:

  // Make sure there is a window object available, and that it has localstorage (old browsers don't)
  const initialState = {
    profile: {},
    // window.localStorage.getItem('id_token') will return null if key not found
    token: window && window.localStorage ? window.localStorage.getItem('id_token') : null,
  }


来源:https://stackoverflow.com/questions/37304862/how-to-use-localstorage-in-unit-tests-with-chai

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!