在Jest测试中,我一直得到“localStorage is not defined”,这是有意义的,但我的选项是什么?碰壁。
当前回答
2022年12月:Nx 14使用Angular 14 Jest。 我们有一个测试设置。Ts文件在每个app和libs文件夹。我们设置本地存储模拟全局。
import 'jest-preset-angular/setup-jest';
Storage.prototype.getItem = jest.fn();
Storage.prototype.setItem = jest.fn();
Storage.prototype.removeItem = jest.fn();
然后localStorage.service.spec.ts文件如下所示:
import { LocalStorageService } from './localstorage.service';
describe('LocalStorageService', () => {
let localStorageService: LocalStorageService;
beforeEach(() => {
localStorageService = new LocalStorageService();
});
it('should set "identityKey" in localStorage', async () => {
localStorageService.saveData('identityKey', '99');
expect(window.localStorage.setItem).toHaveBeenCalled();
expect(window.localStorage.setItem).toHaveBeenCalledWith('identityKey', '99');
expect(window.localStorage.setItem).toHaveBeenCalledTimes(1);
});
it('should get "identityKey" from localStorage', async () => {
localStorageService.getData('identityKey');
expect(window.localStorage.getItem).toHaveBeenCalled();
expect(window.localStorage.getItem).toHaveBeenCalledWith('identityKey');
expect(window.localStorage.getItem).toHaveBeenCalledTimes(1);
});
it('should remove "identityKey" from localStorage', async () => {
localStorageService.removeData('identityKey');
expect(window.localStorage.removeItem).toHaveBeenCalled();
expect(window.localStorage.removeItem).toHaveBeenCalledWith('identityKey');
expect(window.localStorage.removeItem).toHaveBeenCalledTimes(1);
});
});
注:不好意思,这个SatckOverflow窗口很糟糕。
其他回答
上面的答案对我都没用。经过一番挖掘,这就是我要做的。这要归功于一些来源和其他答案。
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 spyRemoveItem = jest.spyOn(window.localStorage, 'removeItem')
就是这样。你可以像以前一样使用你的间谍。
不需要模拟localStorage—只需使用jsdom环境,这样您的测试就可以在类似浏览器的条件下运行。
在你的joke。config。js中,
module.exports = {
// ...
testEnvironment: "jsdom"
}
不幸的是,我在这里找到的解决方案对我不起作用。
所以我在看Jest GitHub的问题,发现了这个帖子
得到最多好评的解决方案是:
const spy = jest.spyOn(Storage.prototype, 'setItem');
// or
Storage.prototype.getItem = jest.fn(() => 'bla');
这对我很有效,
delete global.localStorage;
global.localStorage = {
getItem: () =>
}