最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JSDom 11.12.0 - how to mock localStorage? - Stack Overflow

programmeradmin1浏览0评论

Since the latest release of JSDom, I'm not able to mock localStorage anymore.

I've tried the following methods:

  1. Object.defineProperty(window, 'localStorage', {value: LocalStorageMock})
  2. window.localStorage = LocalStorageMock;
  3. jest.spyOn(window.localStorage, 'setItem')

Any of those methods not worked for me, I get always the original localStorage.

Since the latest release of JSDom, I'm not able to mock localStorage anymore.

I've tried the following methods:

  1. Object.defineProperty(window, 'localStorage', {value: LocalStorageMock})
  2. window.localStorage = LocalStorageMock;
  3. jest.spyOn(window.localStorage, 'setItem')

Any of those methods not worked for me, I get always the original localStorage.

Share Improve this question edited Mar 17, 2019 at 23:26 felixmosh asked Jul 28, 2018 at 8:27 felixmoshfelixmosh 35.5k10 gold badges80 silver badges97 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 8

setItemSpy = jest.spyOn(Storage.prototype, 'setItem'); works for me.

Saw this fix here: https://github.com/facebook/jest/issues/6858#issuecomment-413677180

I actually ran into this same issue when updating Jest, not sure if that's what happened to you but I found this fix here: https://github.com/facebook/jest/issues/6766

From OlivierB-OB:

As a temporary workaround you can install jsdom "11.11.0" (exact) as a dev-dependency in your package. jest-environment-jsdom should then use this version instead of the lastest "11.12.0" causing the behavior. Cheers!

After that I mocked localstorage in test setup and spying was back to normal.

And an implementation of localstorage mock: https://github.com/facebook/jest/issues/2098 lacks removeItem though, so you might need to add it.

You can use the dom-storage package available via npm:

const Storage = require('dom-storage');
global.localStorage = new Storage(null, { strict: true });
global.sessionStorage = new Storage(null, { strict: true });

We use the latest release of jsdom for our unit tests and the above method has worked great.

I've create a function that mocks localStorage. It implements only two methods getItem and setItem. You can easily add other methods if needed.

export const localStorageImpl = {
    register: () => {
        let storage = (window as any).customLocalStorage;

        if(storage) {
            return {
                storage,
                methods: (window as any).customLocalStorageMethods
            }
        }

        storage = (window as any).customLocalStorage = {} as any;

        const setItem = jest.spyOn(Storage.prototype, 'setItem');
        setItem.mockImplementation((key, value) => {
            storage[key] = value;
        });

        const getItem = jest.spyOn(Storage.prototype, 'getItem');
        getItem.mockImplementation((key) => {
            return storage[key];
        });

        const methods = (window as any).customLocalStorageMethods = {
            setItem,
            getItem
        };

        return {
            storage,
            methods
        }
    },
    unregister: () => {
        const methods = (window as any).customLocalStorageMethods;
        if(methods){
            const { setItem, getItem } = methods as { setItem: jest.SpyInstance<void, [key: string, value: string]>, getItem: jest.SpyInstance<string, [key: string]> };
            setItem.mockReset();
            getItem.mockReset();
        }
        delete (window as any).customLocalStorageMethods;
        delete (window as any).customLocalStorage;
    }
}

Usage:

it('should mock localStorage', () => {        
    const { methods } = localStorageImpl.register(); // mock localStorage
    
    const { getByTestId } = render(<Root />);
    fireEvent.click(getByTestId('column-size'));        
    expect(methods.setItem).toBeCalledTimes(1);

    localStorageImpl.unregister();
});
发布评论

评论列表(0)

  1. 暂无评论