Компонент Stateful React с асинхронной функцией не проходит тест Jest - PullRequest
3 голосов
/ 17 июня 2019

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

Мой запрос Pull на репозиторий автора: 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. Мне просто кажется, что мой тест выполняется до того, как состояние закончено, устанавливается?

enter image description here

Компонент 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.log('count:', count);
    this.setState({
      count
    });
  }

  componentDidUpdate() {
    console.log('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 };
  }
}

mocks :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.log('text is:', text);

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

Ответы [ 3 ]

1 голос
/ 18 июня 2019

Проблема заключалась в том, что 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.log('text is:', text);

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

enter image description here

1 голос
/ 24 июня 2019

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

Если импортировать delay следующим образом: import { delay } from 'redux-saga' устранить проблему.= D

0 голосов
/ 18 июня 2019

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

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