Напишите тест-шутку для моего первого компонента

Я только что закончил писать свой первый компонент Reactjs и готов написать несколько тестов (я использовал material-ui и Table из Toggle). Я читал о jest и enzyme, но чувствую, что все еще чего-то не хватает.

Мой компонент выглядит так (упрощенно):

export default class MyComponent extends Component {
    constructor() {
        super()
        this.state = {
            data: []
        }

        // bind methods to this
    }

    componentDidMount() {
        this.initializeData()
    }

    initializeData() {
        // fetch data from server and setStates
    }

    foo() {
        // manuipulatig data
    }

    render() {
        reutrn (
            <Toggle
                id = "my-toggle"
                ...
                onToggle = {this.foo}
            >
            </Toggle>

            <MyTable
                id = "my-table"
                data = {this.state.data}
                ...
            >
            </MyTable>
        )
    }
}

Теперь о тесте. Я хочу написать тест по следующему сценарию:

  1. Feed initializeData с фиктивными данными.
  2. Toggle my-toggle
  3. Данные утверждения изменились (следует ли утверждать сами данные или лучше вместо этого утверждать мою таблицу?)

Итак, я начал с самого начала:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const wrapper = shallow(<MyComponent/>);
    }
})

Я запустил его, но ничего не вышло: ReferenceError: fetch is not defined

Мой первый вопрос: как имитировать initializeData, чтобы избавиться от необходимости вызывать реальный код, использующий выборку?


Я последовал этому ответу: https://stackoverflow.com/a/48082419/2022010 и придумал следующее:

describe('myTestCase', () => {
    it('myFirstTest', () => {
        const spy = jest.spyOn(MyComponent.prototype, 'initializeData'
        const wrapper = mount(<MyComponent/>);
    }
})

Но я все еще получаю ту же ошибку (я также пробовал ее с componentDidMount вместо initializeData, но в итоге получилось то же самое).


Обновлять: Я ошибался. Я получаю сообщение об ошибке "выборка не определена", но на этот раз она исходит из компонента Table (который является оболочкой для таблицы material-ui). Теперь, когда я задумываюсь об этом, у меня действительно много «доделок» ... Интересно, как тогда о них позаботиться.

Может быть, сначала попробуйте поискать ответы - Jest-документы довольно хороши facebook.github.io/jest/docs/en/mock-functions.html

StudioTime 11.06.2018 15:14

@DarrenSweeney Я пробовал этот подход: stackoverflow.com/a/48082419/2022010, но все равно получаю ту же ошибку fetch is not difined :(

Andy Thomas 11.06.2018 15:41

Может можно попробовать Реагировать Тестирование (вместо фермент)

tcconstantin 08.11.2019 17:52

Я бы использовал узел-выборка для определения выборки в среде jest и засовывать для перехвата сетевых вызовов. Сделайте node-fetch глобально доступным и определите для ваших тестов, что сервер возвращает для определенного вызова.

sudavid4 30.04.2020 20:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
4
452
1

Ответы 1

fetch поддерживается в браузере, но jest / энзим выполняется в среде Node, поэтому fetch не является общедоступной функцией в вашем тестовом коде. Есть несколько способов обойти это:

1: Глобально имитируйте fetch - это, вероятно, самое простое решение, но, возможно, не самое чистое.

global.fetch = jest.fn().mockResolvedValue({
  json: () => /*Fake test data*/
  // or mock a response with `.text()` etc if that's what
  // your initializeData function uses
});

2: перенесите ваш вызов fetch на уровень сервиса и внедрите его как зависимость - это сделает ваш код более гибким (хотя и более шаблонным), поскольку вы можете скрыть реализацию fetch за любым интерфейсом, который вы выберете. Затем в любой момент в будущем, если вы решите использовать другую библиотеку выборки, вы можете поменять реализацию на своем уровне обслуживания.

// fetchService.js
export const fetchData = (url) => {
  // Simplified example, only takes 'url', doesn't
  // handle errors or other params.
  return fetch(url).then(res => res.json());
}

// MyComponent.js
import {fetchService} from './fetchService.js'

class MyComponent extends React.Component {
  static defaultProps = {
    // Pass in the imported fetchService by default. This
    // way you won't have to pass it in manually in production
    // but you have the option to pass it in for your tests
    fetchService
  }
  ...
  initializeData() {
    // Use the fetchService from props
    this.props.fetchService.fetchData('some/url').then(data => {
      this.setState({ data });
    })
  }
}

// MyComponent.jest.js
it('myFirstTest', () => {
  const fetchData = jest.fn().mockResolvedValue(/*Fake test data*/);
  const fetchService = { fetchData };
  const wrapper = mount(<MyComponent fetchService = {fetchService} />);
  return Promise.resolve().then(() = {
    // The mock fetch will be resolved by this point, so you can make
    // expectations about your component post-initialization here
  })
}

Другие вопросы по теме