Reactjs & Jest, Тестирующее действие, которое также меняет localStorage - PullRequest
0 голосов
/ 09 сентября 2018

в моем приложении «Resact + 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 или ключ и значение удаляются?

Ответы [ 3 ]

0 голосов
/ 09 сентября 2018

Если вы используете mock для localStorage, смоделируйте все его методы, такие как removeItem, чтобы увидеть, вызывается ли он, вы можете использовать console.log в его mocked-методе.

Внутри 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();
});

Edit:

В качестве окончательного решения обновите ваш jest.config.js для использования testEnvironment: "jsdom", при этом будет использоваться localStorage of jsdom, вам больше не нужно будет его высмеивать.

0 голосов
/ 10 сентября 2018

Спасибо @Аюше и @Александру Ковпашко. Я только что узнал, что если приложение создано CRA, весь подход намного проще. поэтому удалите все пакеты и вернитесь к настройкам CRA по умолчанию. и, насколько мне известно, только один ответ упоминал об этом. Также я искал больше в шутливых документах, где ответ был в 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

0 голосов
/ 09 сентября 2018

По какой-то причине в тестовой среде Jest нет объекта window.localStorage. Я бы порекомендовал вам присвоить макет объекту window. Вы можете сделать это внутри beforeAll метода в вашем тестовом файле или глобально для всех ваших тестов, как описано здесь .

После этого ваш код и тесты будут использовать его как родной 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();
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...