Jest: Есть ли способ протестировать редуктор Redux, который использует условное initialState? - PullRequest
1 голос
/ 12 апреля 2020

Я тестирую редуктор Redux с помощью Jest.

initialState является условным (для определения свойств используются троичные операторы.) Поскольку редуктор не имеет доступа к window в области тестирования, это может только по умолчанию к ложному результату троицы. Это приводит к сбою моего отчета о покрытии.

Здесь я пытаюсь сделать две вещи:

  1. Вызвать редуктор внутри области, которая имеет доступ к window.
  2. Создайте новый initialState внутри этой области и установите значения, основанные на window.

Я пытался .bind(), Jest's jest.fn(), чтобы высмеивать его , но не смог заставить что-либо работать. Затем я понял, что может быть невозможно вызвать initialState, поскольку он определен вне экспорта редуктора. Может быть, require() в нужном месте может создать иную версию, и это можно сделать в новой области видимости с window в ней?

// reducer.js
import constants from '../constants'

const initialState = {
  user: window.user || '',
  token: window.user ? window.user.token : '',
  notification: '',
}

export default (state = initialState, action) => {
  switch (action.type) {
    case constants.FETCH_USER:
      return state.user

     default:
      return state
  }
}
// reducer.test.js
import reducer from './reducer'

const initialState = {
  user: '',
  token: '',
  notification: '',
}

describe('reducer', () => {
  it('should return the initial state', () => {

    // uses initialState without window in scope
    expect(reducer(undefined, {})).toEqual(
      initialState
    )

    const global = {
      window: {
        user: {
          token: 'tag-AAA',
          permissions: true,
        },
      },
    }

    // needs access to window
    expect(reducer.bind(global)(undefined, {})).toEqual(
      {
        user: {
          token: 'tag-AAA',
          permissions: true,
        },
        token: 'tag-AAA',
        notification: '',
      }
    )
  })
})

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

jsdom тестовая среда включена по умолчанию в текущей версии Jest и уже объявляет window, global.window === window. Это причина, по которой набор тестов не дает сбоя при импорте, иначе window.user может вызвать ошибку.

редуктор. js оценивается при импорте, поэтому window в тесте не может повлиять на него , Должен быть повторно импортирован после издевательства window. window макет должен быть сброшен после теста, чтобы избежать перекрестного загрязнения теста.

Это может быть:

const reducer = require('./reducer').default

expect(reducer(undefined, {})).toEqual(initialState)

jest.resetModules()

jest.spyOn(global, 'window', 'get').mockReturnValue({ user: {...} })

const reducer = require('./reducer').default

expect(reducer(undefined, {})).toEqual(...)

...

afterEach(() => {
  jest.restoreAllMocks() // or restoreMocks config option
});
0 голосов
/ 12 апреля 2020

Проблема с вашим текущим кодом заключается в том, что при импорте редуктора устанавливается initialState.

Это приводит к невозможности изменить значения параметров окна перед выполнением другого теста. SCENAR ios. Это означает, что вы не можете выполнить тест, чтобы проверить, когда у вас есть что-то в window.user, и другой, чтобы проверить, когда window.user не определено.

Для того, чтобы сделать это, вам придется изменить как вы определяете начальное состояние в редукторе. Один из способов сделать это - создать метод, который возвращает начальное состояние:

// reducer.js
import constants from '../constants'

const getInitialState = () => ({
    user: window.user || '',
    token: window.user ? window.user.token : '',
    notification: '',
});

export default (state = getInitialState(), action) => {
  switch (action.type) {
    case constants.FETCH_USER:
      return state.user

     default:
      return state
  }
}

Теперь вы можете протестировать оба сценария ios:

describe('reducer', () => {
    it('should return the initial state', () => {
        expect(reducer(undefined, {})).toEqual({
            user: '',
            token: '',
            notification: '',
        });
    });

    it('should return the initial state from window', () => {
        global.user = {
            token: 'tag-AAA',
            permissions: true,
        };

        expect(reducer(undefined, {})).toEqual({
            user: { token: 'tag-AAA', permissions: true, },
            token: 'tag-AAA',
            notification: '',
        });

        // Set the global value to undefined so that it does not affect following tests.
        global.user = undefined;
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...