Смоделируйте зависимость компонента React с помощью Jest

У меня есть компонент реакции (CreateForm). Компонент React зависит от модуля (Store). CreateForm имеет кнопку Отмена. При нажатии кнопки отмены должна быть вызвана функция handleCancel модуля Store.

Я безуспешно написал тест с помощью Jest:

test.only('should handle cancel button click', () => {
    jest.mock('../../src/store');
    const store = require('../../src/store');
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(store.default.handleCancel).toBeCalled();
});

Тест не удался. Имитационная функция не была вызвана, и тест не прошел. Компонент React не получает эту версию макета? Если да, то как исправить тест? Спасибо.

Мой компонент CreateForm выглядит примерно так:

import Store from './store';

render() {
   return (
     <Panel>
       <FormControls />
       <button onClick={Store.create}>Create</button>
       <button onClick={Store.handleCancel}>Cancel</button>
    </Panel>
  );
}

Второй импровизированный тест, который мне подходит, показан ниже.

test.only('should handle cancel button click', () => {
  const store = require('../../src/store').default;
  const cancel = store.handleCancel;
  store.handleCancel = jest.fn();

  const wrapper = shallow(<CreateForm />);
  const cancelButton = wrapper.find('button').at(1);
  cancelButton.simulate('click');
  expect(store.handleCancel).toBeCalled();

  store.handleCancel = cancel;
});

Вышеупомянутый тест работает. Я вручную издеваюсь над функцией, провожу тест и после теста возвращаю функцию к исходному состоянию. Есть ли лучший способ или способ Jest написать вышеуказанный тест? Спасибо.


person vijayst    schedule 30.03.2017    source источник


Ответы (2)


Вот как мне удалось с помощью Jest следить за импортированными функциями.

Импортируйте все, что импортировано в файл, который вы тестируете.

Смоделируйте это в beforeEach, вы можете использовать более сложное издевательство, если вам нужно вернуть значения или что-то еще.

В afterEach вызовите jest.clearAllMocks() для сброса всех функций в нормальное состояние, чтобы не допустить попадания насмешек в другие тесты.

Собираем все вместе, это выглядит примерно так.

import shallow from 'enzyme'
import * as Store from './Store' // This should be the actual path from the test file to the import

describe('mocking', () => {
  beforeEach(() => {
    jest.spyOn(Store, 'handleCancel')
    jest.spyOn(Store, 'create')
  })

  afterEach(() => {
    jest.clearAllMocks();
  })

  test.only('should handle cancel button click', () => {
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(Store.handleCancel).toBeCalled();
  })
})

Кроме того, если вам нужно имитировать импорт по умолчанию, вы можете сделать это следующим образом. jest.spyOn(Store, 'default')

person spirift    schedule 03.04.2017

Вы забыли пошутить, как имитировать модуль магазина, в вашем случае это просто undefined.

const store = require('../../src/store');
jest.mock('../../src/store', () =>({
 handleCancel: jest.fn()
}));

test.only('should handle cancel button click', () => {
    const wrapper = shallow(<CreateForm />);
    const cancelButton = wrapper.find('button').at(1);
    cancelButton.simulate('click');
    expect(store.default.handleCancel).toBeCalled();//I'm not sure about the default here
});

С помощью этого решения вы говорите шутке имитировать магазин с объектом, который имеет функцию handleCancel, которая является шпионской шуткой. Затем вы можете проверить этого шпиона, чтобы он был вызван.

person Andreas Köberle    schedule 31.03.2017
comment
У меня это не работает. CreateForm использует модуль Store. Модуль Store по-прежнему работает с исходным объектом, а не с макетом. Спасибо. - person vijayst; 01.04.2017