typescript - 如何测试一个函数是否使用 Jest 将某些内容设置为 localStorage?

我想测试一个使用 Jest 向 localStorage 写入内容的函数。

有问题的功能如下:

const items: = [
  {
    name: 'Item One',
  },
];

export const init = () => {
  if (!localStorage.getItem('items')) {
    localStorage.setItem('items', JSON.stringify(items));
  }
};

我当前的测试如下所示:

import { init } from './MyComponent';

describe('MyComponent', () => {
  test('init method should set items to localStorage', () => {
    init();
    const items = JSON.parse(localStorage.getItem('items'));
    expect(items).toEqual([
      {
        name: 'Item One',
      },
    ]);
  })
});

我在这里做错了什么或错过了什么?我正在直接导入并调用该函数,但我不确定测试是否像这样有意义。

希望有人可以指导我..

回答1

假设您使用的是 starter create-react-app 项目,localStorage 默认未在测试环境中定义。 https://github.com/facebook/create-react-app/blob/main/docusaurus/docs/running-tests.md#srcsetuptestsjs-1 指导用户进行如下设置(我必须将 as unknown as Storage 添加到 localStorageMock 因为没有它会出现编译错误):

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

这可以添加到您的 setupTests.ts 文件中,也可以添加到您的测试套件文件中 - 在 describe 函数之外,或者在诸如 beforeAll 之类的套件设置函数中。

如您所见,上面明确地模拟了 localStorage 功能,这意味着将要被命中的逻辑将被模拟出来,并且不像在集成测试中那样运行。因此,我会将您的测试重构为以下代码,以确保调用 localStorage 以显示正确的行为:

test('init method should set items to localStorage', () => {
  // act
  init();

  // assert
  expect(localStorageMock.setItem).toHaveBeenCalled();
  // option 1
  expect(localStorageMock.setItem).toHaveBeenCalledWith('items', JSON.stringify([{name: 'Item One'}]))
  // option 2
  const args = localStorageMock.setItem.mock.calls[0];
  expect(args[0]).toEqual('items');
  expect(JSON.parse(args[1])[0].name).toEqual('Item One');
})

希望这可以帮助你!

相似文章

最新文章