How do I deal with localStorage in jest tests?

后端 未结 17 1684
长情又很酷
长情又很酷 2020-11-28 02:01

I keep getting \"localStorage is not defined\" in Jest tests which makes sense but what are my options? Hitting brick walls.

相关标签:
17条回答
  • 2020-11-28 02:38

    Great solution from @chiedo

    However, we use ES2015 syntax and I felt it was a little cleaner to write it this way.

    class LocalStorageMock {
      constructor() {
        this.store = {};
      }
    
      clear() {
        this.store = {};
      }
    
      getItem(key) {
        return this.store[key] || null;
      }
    
      setItem(key, value) {
        this.store[key] = value.toString();
      }
    
      removeItem(key) {
        delete this.store[key];
      }
    };
    
    global.localStorage = new LocalStorageMock;
    
    0 讨论(0)
  • 2020-11-28 02:38

    You can use this approach, to avoid mocking.

    Storage.prototype.getItem = jest.fn(() => expectedPayload);
    
    0 讨论(0)
  • 2020-11-28 02:44

    If using create-react-app, there is a simpler and straightforward solution explained in the documentation.

    Create src/setupTests.js and put this in it :

    const localStorageMock = {
      getItem: jest.fn(),
      setItem: jest.fn(),
      clear: jest.fn()
    };
    global.localStorage = localStorageMock;
    

    Tom Mertz contribution in a comment below :

    You can then test that your localStorageMock's functions are used by doing something like

    expect(localStorage.getItem).toBeCalledWith('token')
    // or
    expect(localStorage.getItem.mock.calls.length).toBe(1)
    

    inside of your tests if you wanted to make sure it was called. Check out https://facebook.github.io/jest/docs/en/mock-functions.html

    0 讨论(0)
  • 2020-11-28 02:44

    This worked for me,

    delete global.localStorage;
    global.localStorage = {
    getItem: () => 
     }
    
    0 讨论(0)
  • 2020-11-28 02:45

    A better alternative which handles undefined values (it doesn't have toString()) and returns null if value doesn't exist. Tested this with react v15, redux and redux-auth-wrapper

    class LocalStorageMock {
      constructor() {
        this.store = {}
      }
    
      clear() {
        this.store = {}
      }
    
      getItem(key) {
        return this.store[key] || null
      }
    
      setItem(key, value) {
        this.store[key] = value
      }
    
      removeItem(key) {
        delete this.store[key]
      }
    }
    
    global.localStorage = new LocalStorageMock
    
    0 讨论(0)
  • 2020-11-28 02:46

    The following solution is compatible for testing with stricter TypeScript, ESLint, TSLint, and Prettier config: { "proseWrap": "always", "semi": false, "singleQuote": true, "trailingComma": "es5" }:

    class LocalStorageMock {
      public store: {
        [key: string]: string
      }
      constructor() {
        this.store = {}
      }
    
      public clear() {
        this.store = {}
      }
    
      public getItem(key: string) {
        return this.store[key] || undefined
      }
    
      public setItem(key: string, value: string) {
        this.store[key] = value.toString()
      }
    
      public removeItem(key: string) {
        delete this.store[key]
      }
    }
    /* tslint:disable-next-line:no-any */
    ;(global as any).localStorage = new LocalStorageMock()
    

    HT/ https://stackoverflow.com/a/51583401/101290 for how to update global.localStorage

    0 讨论(0)
提交回复
热议问题