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?
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?
Share Improve this question edited Oct 13, 2021 at 15:45 AncientSwordRage 7,63521 gold badges99 silver badges191 bronze badges asked May 18, 2016 at 16:07 Max PMax P 1,4594 gold badges15 silver badges33 bronze badges4 Answers
Reset to default 7I 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.
I solve problem with mock-local-storage My run test mand is:
mocha -r mock-local-storage --pilers js:babel-core/register --recursive
For testing purposes I remend 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')
})
})
})
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,
}