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

How to test if a function set something to localStorage with Jest?

我想测试一个使用 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',
      },
    ]);
  })
});

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

希望有人能指导我..

假设您使用的是入门 create-react-app 项目,localStorage 默认情况下未在测试环境中定义。 documentation 指示用户进行如下设置(我必须将 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');
})

希望对您有所帮助!