【问题标题】:Reactjs&Jest, Testing action that also changes localStorageReactjs&Jest,也改变 localStorage 的测试动作
【发布时间】:2019-02-14 08:07:10
【问题描述】:

在我的 react + redux 应用程序中,我有一个动作,除了返回类型和有效负载之外,还会更改 localStorage,例如:

export const cancel = () => {
  localStorage.removeItem("MyAppData");
  return { type: types.USER_CANCEL};
};

我的测试看起来像:

test("user cancels", () => {
  const action = actions.cancel();
  expect(action).toEqual({
    type: types.USER_CANCEL
  });
});

我没有为本地存储编写测试

  ● user cancels

    ReferenceError: localStorage is not defined

      33 |
      34 | export const cancel = () => {
    > 35 |   localStorage.removeItem("MyAppData");
         |   ^
      36 |   return { type: types.USER_CANCEL};
      37 | };
      38 |

      at Object.localStorage [as cancel] (src/actions/AllActions.js:35:3)
      at Object.cancel (__test__/actions/AllActions.test.js:56:26)

因此我为本地存储做了一个模拟

const mockStorage = {};
const localStorage = {
  setItem: (key, val) => Object.assign(mockStorage, { [key]: val }),
  getItem: key => mockStorage[key],
  removeItem: key => {delete mockStorage[key];console.log("Deleted: ", key);},
  clear: () => mockStorage
};
export default localStorage;

无论是导入这个模拟还是使用 localStorage API,我仍然得到同样的错误

我对如何测试当我调用cancel() 时也调用localStorge.removeItem 或删除键和值感到困惑?

【问题讨论】:

    标签: reactjs jestjs


    【解决方案1】:

    出于某种原因,Jest 的测试环境中没有 window.localStorage 对象。我建议您将模拟分配给 window 对象。您可以在测试文件中的 beforeAll 方法中执行此操作,也可以按照here 所述在全局范围内执行所有测试。

    之后,您的代码和测试会将其用作本机 localStorage:

    test("user cancels", () => {
      localStorage.setItem("MyAppData", "some_data");
    
      const action = actions.cancel();
      expect(action).toEqual({
        type: types.USER_CANCEL
      });
    
      expect(localStorage.getItem("MyAppData")).toBeNull();
    });
    

    【讨论】:

    • 嗨,谢谢,但是当不使用模拟时,我得到 ReferenceError: localStorage is not defined in test,并且当导入模拟时,动作本身会出现相同的错误
    • 如果您的测试环境不是jsdom,可能会发生这种情况。因为 node.js 没有localStorage。也许this 会有所帮助。
    • 我应该如何识别?我已经使用 create-react-app CLI 和所有带有 .babelrc 的玩笑的 babel 插件创建。
    • 即使我没有写任何关于本地存储的测试,只是再次检查返回“类型”我得到同样的错误
    • 嗨,再次 :) 如果有帮助,我已经编辑了带有错误日志的问题
    【解决方案2】:

    如果要模拟 localStorage,请模拟其所有方法,例如 removeItem,以查看它是否被调用,您可以在其模拟方法中使用 console.log。

    在 jest.config.js 中

    添加

      setupFiles: [
        './jest.globals.js'
      ],
    

    jest.globals.js

    const mockStorage = {};
    const localStorage = {
      setItem: (key, val) => Object.assign(mockStorage, {[key]: val}),
      getItem: key => mockStorage[key],
      removeItem: key => { delete mockStorage[key]; console.log('Deleted: ' + key); },
      clear: () => mockStorage,
    };
    global.localStorage = localStorage;
    

    现在 localStorage 将在您的整个测试过程中在全球范围内可用。

    测试:

    test("user cancels", () => {
         const action = actions.cancel();
          expect(action).toEqual({
            type: types.USER_CANCEL
          });
    
          expect(localStorage.getItem("MyAppData")).toBeNull();
    });
    

    编辑:

    作为最终解决方案,更新您的 jest.config.js 以使用 testEnvironment: "jsdom" 这将使用 jsdom 的 localStorage,您不再需要模拟它。

    【讨论】:

    • 如果不调用 removeItem 方法,console.log 不会使您的测试失败。你应该只依赖断言。
    • 它回答了如何测试localStorge.removeItem 是否被调用,并更新它的断言。
    • 但是你的回答可以理解为建议通过console.log测试逻辑。可能将“为了测试它是否被调用”替换为“为了查看它是否被调用”将解决这个歧义。
    • 当然,这样会更清晰。
    • @Ayushya 谢谢,但是当我不使用模拟时,我得到 ReferenceError: localStorage is not defined in the action file itself and when importing mock get the error in test file。我哪里错了?
    【解决方案3】:

    感谢@Ayushya 和@Oleksandr Kovpashko。我刚刚发现如果应用程序是由 CRA 创建的,那么整个方法要简单得多。所以卸载了所有软件包并恢复为 CRA 默认值。据我所知,only one answer 提到了这一点。此外,我在 jest docs 中搜索了更多答案,其中答案在 CRA docs

    所以创建src/setupTests.js

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

    默认情况下CRA的测试脚本是

     "test": "react-scripts test --env=jsdom",
    

    可以改成node

    【讨论】:

      猜你喜欢
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 2020-11-16
      • 1970-01-01
      • 2018-12-28
      • 2019-07-20
      • 2021-08-11
      相关资源
      最近更新 更多