Как протестировать componentDidMount при помощи jest и enzyme, в котором вызывается функция не из props

125
28 октября 2019, 01:00

Подскажите, как можно протестировать данный компонент при помощи jest и enzyme.

  componentDidMount = () => {
    this.getCatalog()
  }
  getCatalog = async () => {
    try {
      const getApiData = await Axios.get(`${URL_GET}`)
      this.setState({
        data: getApiData.data,
        loading: false
      })
    } catch {
      this.setState({
        errorMsg: 'Ошибка при подключении'
      })
    }
  }

Необходимо протестировать метод getCatalog, заменив его mock функцией, но я не могу разобраться, как подменить родную функцию.

describe('App test componentDidMount', () => {
  const mockFetchGetCatalog = jest.fn()
  const props = {
    getCatalog: mockFetchGetCatalog
  }
  const AppContainer = shallow(<App {...props}/>)
  it('renders properly', () => {
    expect(AppContainer).toMatchSnapshot()
  })
  it('запрос на сервер', () => {
    expect(AppContainer).toHaveBeenCalledTimes(1) // создали ожидание с нужным ассертом
  })
})

так бы тест выглядел, если бы метод вызывался из пропсов

Answer 1

Такой подход должен сработать:

describe('Test componentDidMount', () => {
  // создать функцию-шпион на метод getCatalog для компонента App
  const spy = jest.spyOn(App.prototype, 'getCatalog');
  // монтритуем компонент App, а значит вызываем componentDidMount
  const wrapper = mount(<App />);
  // при этом можно явно вызвать метод: `wrapper.instance().getCatalog();`
  it('Method getCatalog have been called', () => {
    // во время вызова метода componentDidMount должен был вызваться getCatalog
    expect(spy).toHaveBeenCalledTimes(1)
  })   
})

Обращаю Ваше внимание на то, что shallow не вызывает componentDidMount и componentDidUpdate, поэтому нужно использовать mount. Однако если предложенный вариант не сработает, то я предложу написать другой тест, в котором проверить вызов componentDidMount, а потом уже проверить вызов функции getCatalog, причем попробуем написать в двух разным методах. Однако при этом используем фугкцию-шпион не из jest а из sinon. Пример кода:

import { mount } from 'enzyme';
import sinon from 'sinon';
import App from './App';
describe('<App /> componentDidMount', () => {
  // ожидаем, что componentDidMount будет вызван один раз
  it('calls componentDidMount', () => {
    sinon.spy(App.prototype, 'componentDidMount');
    const wrapper = mount(<App />);
    expect(App.prototype.componentDidMount).to.have.property('callCount', 1);
  });
})
describe('<App /> getCatalog', () => {
  // ожидаем, что getCatalog будет вызван один раз
  it('calls getCatalog', () => {
    sinon.spy(App.prototype, 'getCatalog');
    const wrapper = mount(<App />);
    expect(App.prototype.getCatalog).to.have.property('callCount', 1);
  });
})

Если что-то не так работает, но пишите точки останова через debugger; и отлаживайте тест, всё должно работать, а если не работает, то значит что-то просто идет не так

READ ALSO
js считает +1 год в дни рождения

js считает +1 год в дни рождения

Неправильно считает день рожденият,е если сегодня 26 февраля 2019, а др стоит где-нибудь 10

116
Задержка в each

Задержка в each

как сделать задержку на переход к следующему элементу и событие submit? есть формы у товара с разными размерами

112
Slider Range ввод в поле

Slider Range ввод в поле

подскажите как обработать ввод в инпуты и чтобы ползунок менял значение

111