Reputation: 4669
I would like to mock localStorage methods in jest for error simulation. I have localstorage getter and setter methods defined in utility.js. I would like to mock localStorage.setItem
to throw an error when utility.setItem
is called.
//file: utility.js
export default {
getItem(key) {
return localStorage.getItem(key);
},
setItem(key, value) {
localStorage.setItem(key, value);
}
};
In jest,
test('throw error', () => {
localStorage.setItem = jest.fn(() => {
console.log(" called ");
throw new Error('ERROR');
});
utility.setItem('123', 'value');
});
However localStorage.setItem
mock is never getting called. I have also tried doing
window.localStorage.setItem = jest.genMockFunction(()=>{console.log(" Mock Called")});
global.localStorage.setItem = jest.fn(()=>{console.log(" Mock Called")});
Upvotes: 7
Views: 29142
Reputation: 5450
Here is the TS version of https://github.com/facebook/jest/issues/6798#issuecomment-440988627
import { afterAll, beforeAll } from '@jest/globals';
const mockWindowProperty = <P extends keyof Window>(property: P, value: Partial<Window[P]>) => {
const { [property]: originalProperty } = window;
delete window[property];
beforeAll(() => {
Object.defineProperty(window, property, {
configurable: true,
writable: true,
value,
});
});
afterAll(() => {
window[property] = originalProperty;
});
};
export default mockWindowProperty;
Upvotes: 0
Reputation: 693
If you want to test localStorage functions then I would like to suggest the jest-localstorage-mock npm package.
After configuring this package in your setup test file as per documentation, then you could do this after.
test('should save to localStorage', () => {
const KEY = 'foo',
VALUE = 'bar';
dispatch(action.update(KEY, VALUE));
expect(localStorage.setItem).toHaveBeenLastCalledWith(KEY, VALUE);
expect(localStorage.__STORE__[KEY]).toBe(VALUE);
expect(Object.keys(localStorage.__STORE__).length).toBe(1);
});
test('should have cleared the sessionStorage', () => {
dispatch(action.reset());
expect(sessionStorage.clear).toHaveBeenCalledTimes(1);
expect(sessionStorage.__STORE__).toEqual({}); // check store values
expect(sessionStorage.length).toBe(0); // or check length
});
Upvotes: 3
Reputation: 111042
To access something that is in the global scope of your module under test, you need to use the global
namespace. So to access localStorage
use global.localStorage
:
global.storage = {
store:{},
getItem: (key)=>this.store[key],
setItem: (key, value)=> this.store[key] = value
}
Upvotes: 1
Reputation: 730
jest.spyOn(window.localStorage.__proto__, 'setItem');
works with nothing else at all needed, as noted here: https://github.com/facebook/jest/issues/6798#issuecomment-440988627
Upvotes: 24
Reputation: 4669
This goes inline with what Andreas suggested in the answer, but i was able to mock it using Storage interface. I did something like this,
In jest,
test('throw error', () => {
Storage.prototype.setItem = jest.fn(() => {
console.log(" called "); // <-- was called
throw new Error('ERROR');
});
utility.setItem('123', 'value');
});
Also this PR discussion was helpful.
Upvotes: 6