在Jest测试中,我一直得到“localStorage is not defined”,这是有意义的,但我的选项是什么?碰壁。


当前回答

上面的答案对我都没用。经过一番挖掘,这就是我要做的。这要归功于一些来源和其他答案。

https://www.codeblocq.com/2021/01/Jest-Mock-Local-Storage/ https://github.com/facebook/jest/issues/6798#issuecomment-440988627 https://gist.github.com/mayank23/7b994385eb030f1efb7075c4f1f6ac4c https://github.com/facebook/jest/issues/6798#issuecomment-514266034

我的全部要点:https://gist.github.com/ar-to/01fa07f2c03e7c1b2cfe6b8c612d4c6b

/**
 * Build Local Storage object
 * @see https://www.codeblocq.com/2021/01/Jest-Mock-Local-Storage/ for source
 * @see https://stackoverflow.com/a/32911774/9270352 for source
 * @returns
 */
export const fakeLocalStorage = () => {
  let store: { [key: string]: string } = {}

  return {
    getItem: function (key: string) {
      return store[key] || null
    },
    setItem: function (key: string, value: string) {
      store[key] = value.toString()
    },
    removeItem: function (key: string) {
      delete store[key]
    },
    clear: function () {
      store = {}
    },
  }
}

/**
 * Mock window properties for testing
 * @see https://gist.github.com/mayank23/7b994385eb030f1efb7075c4f1f6ac4c for source
 * @see https://github.com/facebook/jest/issues/6798#issuecomment-514266034 for sample implementation
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Window#properties for window properties
 * @param { string } property window property string but set to any due to some warnings
 * @param { Object } value for property
 *
 * @example
 *
 *  const testLS = {
 *    id: 5,
 *    name: 'My Test',
 *  }
 * mockWindowProperty('localStorage', fakeLocalStorage())
 * window.localStorage.setItem('currentPage', JSON.stringify(testLS))
 *
 */
const mockWindowProperty = (property: string | any, value: any) => {
  const { [property]: originalProperty } = window
  delete window[property]
  beforeAll(() => {
    Object.defineProperty(window, property, {
      configurable: true,
      writable: true,
      value,
    })
  })
  afterAll(() => {
    window[property] = originalProperty
  })
}

export default mockWindowProperty

其他回答

在我的例子中,我需要在检查localStorage值之前设置它。

我所做的就是

const data = { .......}

const setLocalStorageValue = (name: string, value: any) => {
  localStorage.setItem(name, JSON.stringify(value))
}



 describe('Check X class', () => {
  setLocalStorageValue('Xname', data)
  const xClass= new XClass()

  console.log(xClass.initiate()) ; // it will work 

  
})

我从github找到了这个解决方案

var localStorageMock = (function() {
  var store = {};

  return {
    getItem: function(key) {
        return store[key] || null;
    },
    setItem: function(key, value) {
        store[key] = value.toString();
    },
    clear: function() {
        store = {};
    }
  }; 
})();

Object.defineProperty(window, 'localStorage', {
 value: localStorageMock
});

您可以在setupTests中插入这段代码,它应该可以正常工作。

我在一个使用typesctipt的项目中测试了它。

答:

目前(7月22日)localStorage不能像你通常会被嘲笑或监视,并在创建-反应-应用程序文档中概述。这是由于jsdom中所做的更改。你可以在jest和jsdom问题跟踪器中读到它。

作为一种变通方法,你可以监视原型:

// does not work:
jest.spyOn(localStorage, "setItem");
localStorage.setItem = jest.fn();

// either of these lines will work, different syntax that does the same thing:
jest.spyOn(Storage.prototype, 'setItem');
Storage.prototype.setItem = jest.fn();

// assertions as usual:
expect(localStorage.setItem).toHaveBeenCalled();

关于监视原型机的注意事项:

监视实例使您能够观察和模拟特定对象的行为。

另一方面,监视原型,将同时观察/操作该类的每个实例。除非您有一个特殊的用例,否则这可能不是您想要的。

但是,在本例中没有区别,因为localStorage只存在一个实例。

至少到目前为止,localStorage可以很容易地在你的笑话测试中被监视,例如:

const spyRemoveItem = jest.spyOn(window.localStorage, 'removeItem')

就是这样。你可以像以前一样使用你的间谍。

Object.defineProperty(window, "localStorage", {
  value: {
    getItem: jest.fn(),
    setItem: jest.fn(),
    removeItem: jest.fn(),
  },
});

or

jest.spyOn(Object.getPrototypeOf(localStorage), "getItem");
jest.spyOn(Object.getPrototypeOf(localStorage), "setItem");