Как имитировать выборку при тестировании приложения React? - PullRequest
0 голосов
/ 16 июня 2020

Я хотел бы протестировать небольшое веб-приложение React, в котором я использую глобальный метод fetch.

Я пытался имитировать fetch таким образом:

global.fetch = jest.spyOn(global, 'fetch').mockImplementation(endpoint =>
  Promise.resolve({
    json: () => Promise.resolve(mockResponse)
  })
);

. .. но макет, кажется, игнорируется, в то время как встроенный fetch, похоже, используется: Error: connect ECONNREFUSED 127.0.0.1:80 ... выглядит как неудачный вызов встроенного fetch.

Затем я попытался используйте jest.fn вместо jest.spyOn:

global.fetch = jest.fn(endpoint =>
  Promise.resolve({
    json: () => Promise.resolve(mockResponse)
  })
);

... и был удивлен, увидев другую ошибку. Теперь макет, кажется, принят во внимание, но в то же время работает некорректно:

    TypeError: Cannot read property 'then' of undefined

       8 |     this.updateTypes = this.props.updateTypes;
       9 |     this.updateTimeline = this.props.updateTimeline;
    > 10 |     fetch('/timeline/tags')
         |     ^
      11 |       .then(res => res.json())
      12 |       .then(tags => tags.map(tag => <option value={tag} key={tag} />))
      13 |       .then(options => options.sort((a, b) => a.key.localeCompare(b.key)))

Честно говоря, я нахожу документацию Jest и React Testing Library немного запутанной. В чем может быть проблема с тем, что я делаю?

Edit

Компонент React, который я пытаюсь протестировать, называется «App», был создан с помощью Create React App и был изменен для включения звонок на fetch. Я с радостью могу предоставить код для этого компонента, но я считаю, что проблема заключается в тестах.

В начале моего файла App.test.js я import React from 'react';, затем import { render, fireEvent, waitFor, screen } from '@testing-library/react'; и, наконец, import App from './App';. Впоследствии я пытаюсь имитировать fetch одним из описанных мной способов, а затем объявляю следующий тест:

test('renders a list of items, upon request', async () => {
  const app = render(<App />);

  fireEvent.click(screen.getByText('Update'));

  await waitFor(() => screen.getByRole('list'));

  expect(screen.getByRole('list')).toBeInTheDocument();
  expect(screen.getByRole('list')).toHaveClass('Timeline');
});

Наконец, я заканчиваю свой тестовый файл global.fetch.mockRestore();.

1 Ответ

0 голосов
/ 16 июня 2020

Ошибка ECONNREFUSED вместо fetch is not defined означает, что fetch был полифилен. Он не является частью JSDOM и не заполняется самим Jest, а указывается c в текущей настройке. В этом случае полифил предоставляется приложением create-react-app.

Всегда предпочтительно имитировать существующую глобальную функцию с помощью jest.spyOn, а не назначать их как свойства global, это позволяет Jest выполнить очистку . Такие вещи, как global.fetch = jest.spyOn(global, 'fetch'), никогда не должны выполняться, потому что это предотвращает восстановление fetch. Это может объяснить ошибку TypeError: Cannot read property 'then' of undefined для, казалось бы, правильно имитируемой функции.

Правильный и безопасный способ имитировать глобальные объекты - это имитировать их перед каждым тестом и восстанавливать после каждого теста:

beforeEach(() => {
  jest.spyOn(global, 'fetch').mockResolvedValue({
    json: jest.fn().mockResolvedValue(mockResponse)
  })
});

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

Там не должно быть никаких других модификаций global.fetch, чтобы макет работал правильно.

Предпочтительный способ восстановить макеты и шпионы - использовать параметр конфигурация вместо jest.restoreAllMocks, потому что не это может привести к случайному перекрестному загрязнению теста, что нежелательно.

Другая причина появления ошибки TypeError: Cannot read property 'then' of undefined заключается в том, что Jest неправильно указывает на строку fetch, а ошибка фактически относится к другой строке. Это может произойти, если исходные карты работают некорректно. Если fetch имитируется правильно, и в том же компоненте есть другие then, это правдоподобное объяснение ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...