Компонент Stateful React с асинхронной функцией не прошел тест Jest

Я слежу за этим Учебное пособие по тесту Jest на Pluralsight здесь. И я написал код точно так же, как автор, но мой тест почему-то не проходит.

Мой запрос на включение в репозиторий автора: https://github.com/danielstern/isomorphic-react/pull/19

У меня есть простой компонент React, он обновляет свое состояние count с помощью асинхронного/ожидающего вызова службы в componentDidMount.

{this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : 'Loading...'}

ОЖИДАЛ

Поскольку я издевался над NotificationsService и установил для счетчика значение 42, тест должен пройти с текстом внутри компонента как "42 Notifications Awaiting!"

РЕЗУЛЬТАТЫ

Текст остается застрявшим по умолчанию Loading...

Я правильно издевался над сервисом, и переменная count даже правильно регистрируется как 42! Однако this.state.count все еще -1, поэтому вместо отображения: ${this.state.count} Notifications Awaiting он по-прежнему отображает Loading... и, таким образом, не проходит тест.


Что я пробовал

1) Пробовал добавлять 1000 к задержке.

2) Пробовал использовать setTimeout внутри теста.

3) Пробовал jest.useFakeTimers(); и jest.runAllTimers();

Однако ничего не работает, count внутри компонента застрял на -1, хотя count установлено на 42. Мне просто кажется, что мой тест выполняется до завершения установки состояния?

Компонент Stateful React с асинхронной функцией не прошел тест Jest

Компонент NotificationsViewser.jsx

import React from 'react';
import NotificationsService from '../services/NotificationsService';

export default class componentName extends React.Component {
  constructor(...args) {
    super(...args);

    this.state = {
      count: -1
    }
  }

  async componentDidMount () {
    let { count } = await NotificationsService.GetNotifications();
    console.info('count:', count);
    this.setState({
      count
    });
  }

  componentDidUpdate() {
    console.info('componentDidUpdate:', this.state);
  }

  render() {
    return (
      <div className = "mt-3 mb-2">
        <div className = "notifications">
          {this.state.count != -1 ? `${this.state.count} Notifications Awaiting` : `Loading...`}
        </div>
      </div>
    )
  }
}

NotificationsService.js

import { delay } from 'redux-saga';

export default {
  async GetNotifications() {
    console.warn("REAL NOTIFICATION SERVICE! CONTACTING APIS!");

    await delay(1000);
    return { count: 42 };
  }
}

издевается: NotificationsService.js

let count = 0;

export default {
  __setCount(_count) {
    count = _count;
  },
  async GetNotifications() {
    console.warn("GOOD JOB! USING MOCK SERVICE");
    return { count };
  }
}

Ну наконец то...

Тест

import React from 'react';
import renderer from 'react-test-renderer';
import delay from 'redux-saga';

import NotificationsViewer from '../NotificationsViewer';

jest.mock('../../services/NotificationsService');

const notificationService = require('../../services/NotificationsService').default;

describe('The notification viewer', () => {

  beforeAll(() => {
    notificationService.__setCount(42);
  });

  it('should display the correct number of notifications', async() => {
    const tree = renderer
      .create(
        <NotificationsViewer/>
      );

    await delay();

    const instance = tree.root;
    const component = instance.findByProps({className: `notifications`});
    const text = component.children[0];
    console.info('text is:', text);

    expect(text).toEqual('42 Notifications Awaiting!');
  });
})

Мне кажется, что await delay() не позволяет запускать методы жизненного цикла до того, как будет протестирован блок expect. Поскольку результаты console.info('text is:', text); обрабатываются первыми, затем обрабатываются журналы componentDidMount и componentDidUpdate.

Leon Gaban 18.06.2019 18:41
Поведение ключевого слова "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) для оценки ваших знаний,...
3
1
565
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Может быть, ваша describe также должна быть асинхронной функцией? await операторы должны быть объявлены внутри async области, не так ли?

Итак, я только что попробовал это, но получил это предупреждение> Возврат обещания из «описания» не поддерживается. Тесты должны быть определены синхронно. Возврат значения из «describe» не пройдет тест в будущей версии Jest.

Leon Gaban 17.06.2019 23:02

Упс, я пропустил async в блоке it

paulinhorocha 17.06.2019 23:03

Проблема заключалась в том, что await delay() не работал, чтобы все методы жизненного цикла React, такие как componentDidMount, создавали/вызывали.

Мне пришлось использовать Enzyme, хотя автор не рекомендовал его из-за большого количества открытых проблем с ошибками.

Используя Enzyme, я мог убедиться, что componentDidMount вызывается, и, таким образом, установить состояние count на 42 с помощью имитируемого сервиса.

Мне также нужно было установить следующие пакеты:

"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",

Фиксированный тест

import React from 'react';
import renderer from 'react-test-renderer';
import Adapter from 'enzyme-adapter-react-16';
import { shallow, configure } from 'enzyme';

configure({adapter: new Adapter()});

import NotificationsViewer from './NotificationsViewer';

jest.mock('../services/NotificationsService');

const notificationService = require('../services/NotificationsService').default;

notificationService.default = jest.fn();

describe('The notification viewer', () => {

  beforeAll(() => {
    notificationService.__setCount(42);
  });

  // it('pass', () => {});

  it('should display the correct number of notifications', async() => {
    const tree = renderer.create(<NotificationsViewer />);
    const wrapper = shallow(<NotificationsViewer />);
    const instance = tree.root;

    await wrapper.instance().componentDidMount();

    const component = instance.findByProps({className: `notifications`});
    const text = component.children[0];
    console.info('text is:', text);

    expect(text).toEqual('42 Notifications Awaiting');
  });
})

Ответ принят как подходящий

На самом деле, настоящая проблема была в файле isomorphic-react/src/components/__tests__/NotificationsViewer.js. delay импортированы неправильно, и это вызывало ошибку при тестировании.

При импорте delay вот так: import { delay } from 'redux-saga' устраните проблему. = Д

Это правильно, у меня был неправильный импорт. Однако я оставлю свой ответ ниже в качестве предпочтительного способа справиться с этим, поскольку не каждый проект будет использовать redux-saga, и мой пример объясняет, как использовать Enzyme для решения этой проблемы :)

Leon Gaban 24.06.2019 17:20

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