when i try to mock the localStorage of a react component in jest as below,
spyOn(window.localStorage,'removeItem');
window.localStorage.removeItem("key1");
window.localStorage.removeItem("key2");
expect(window.localStorage.removeItem).toHaveBeenCalledWith("key1");
expect(window.localStorage.removeItem).toHaveBeenCalledWith("key2");
and used the below code for localStorage mocking
let localStorageMock = (function() {
var storage = {};
return {
setItem: function(key, value) {
storage[key] = value || '';
},
getItem: function(key) {
return storage[key] || null;
},
removeItem: function(key) {
delete storage[key];
},
get length() {
return Object.keys(storage).length;
},
key: function(i) {
var keys = Object.keys(storage);
return keys[i] || null;
}
};
})();
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
To mock localStorage methods with Jest, we call jest.spyOn. jest.spyOn (window.localStorage.__proto__, "setItem"); to call jest.spyOn with window.localStorage.__proto__, which is the local storage prototype. We mock the localStorage.setItem method by calling spyOn with 'setItem' as the 2nd argument.
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")}); Show activity on this post.
to create the localStorageMock object by creating an IIFE that returns an object that manipulates the store object. It has getItem to return store [key]. setItem sets store [key] to value converted to a string.
In short: localStorage is actually an instance of a Storage class. Sadly, mocking methods on a class instance (i.e. localStorage.getItem) doesn't work with our jest.fn approach. But don't fret!
I've done this for session storage for store testing by adding a setup environment script file with the following in;
Object.defineProperty(window, 'sessionStorage', { value: {}, writable: true });
The package.json file then looks like;
"jest": {
"setupTestFrameworkScriptFile": "jest/jest-setupTestFrameworkScriptFile.js",
}
I'm not actually convinced you need this in the latest version of jest however I've used this setup since a much earlier version.
One thing when using this approach you need to be aware of is that it can persist data between tests so you'll want to add the following in the beforeEach;
sessionStorage = {};
I used this in my project's package.json
:
"jest": {
"setupFiles": ["<rootDir>/app/mock/localStorageMock.js"]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With