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


当前回答

在这里引用了一些其他的答案来解决一个用Typescript的项目。我像这样创建了一个LocalStorageMock:

export class LocalStorageMock {

    private store = {}

    clear() {
        this.store = {}
    }

    getItem(key: string) {
        return this.store[key] || null
    }

    setItem(key: string, value: string) {
        this.store[key] = value
    }

    removeItem(key: string) {
        delete this.store[key]
    }
}

然后我创建了一个LocalStorageWrapper类,我使用它来访问应用程序中的所有本地存储,而不是直接访问全局本地存储变量。便于在包装器中为测试设置模拟。

其他回答

或者你只是像这样使用一个模拟包:

https://www.npmjs.com/package/jest-localstorage-mock

它不仅处理存储功能,还允许您测试是否实际调用了存储。

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窗口很糟糕。

以下解决方案兼容更严格的TypeScript、ESLint、TSLint和Prettier配置测试:{"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了解如何更新global.localStorage

2021年,打印稿

class LocalStorageMock {
  store: { [k: string]: string };
  length: number;

  constructor() {
    this.store = {};
    this.length = 0;
  }

  /**
   * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage/key
   * @returns
   */
  key = (idx: number): string => {
    const values = Object.values(this.store);
    return values[idx];
  };

  clear() {
    this.store = {};
  }

  getItem(key: string) {
    return this.store[key] || null;
  }

  setItem(key: string, value: string) {
    this.store[key] = String(value);
  }

  removeItem(key: string) {
    delete this.store[key];
  }
}

export default LocalStorageMock;

然后你可以用它

global.localStorage = new LocalStorageMock();

正如Niket Pathak在评论中提到的, 从jest@24 / jsdom@11.12.0及以上开始,localStorage将自动被模拟。