Как проверить реагирующий компонент после выборки данных в componentDidMount? - PullRequest
0 голосов
/ 25 августа 2018

У меня есть компонент реагирования, который рендерится условно (рендерится, если данные извлекаются, в противном случае возвращает ноль), и я хочу проверить это с помощью jest & enzyme. Проблема, с которой я столкнулся, заключается в том, что я хочу протестировать один из методов в классе, но .instance() продолжает возвращать ноль, поэтому он не позволяет мне тестировать экземпляр.

мой код выглядит примерно так

export default class MyComponent extends React.Component<Props, State> {
    componentDidMount() {
        this.props.fetchData.then(() => 
            this.setState({ loaded: true });
        );
    }

    methodThatIWantToTest() {
        //do some stuff here
    }

    render() {
        if (this.loaded) {
            // render stuff here
        } else {
            return null;
        }
    }
}

и в тесте хочу проверить

describe('myComponent', () => {
   it('should do some stuff', () => {
      const shallowWrapper = shallow(<MyComponent {...props}/>);
      const method = shallowWrapper.instance().methodThatIWantToTest();
      ....such and such

   });
});

но похоже, что MyComponent возвращает только ноль, поэтому shallowWrapper.instance() также возвращает ноль. Я пробовал shallowWrapper.update() и многие другие вещи, но, похоже, он вообще не хочет рендериться. Как мне дождаться обновления моего компонента, а затем запустить оператор expect?

кто-нибудь имел проблему, похожую на мою, и знает, как обойти это?

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Это render результат, а не экземпляр null. shallowWrapper.instance() является экземпляром класса компонента, он не может быть null для компонента с состоянием. Как ссылка гласит:

Возвращает (Реакт 16.x)

ReactComponent: экземпляр компонента React с сохранением состояния.

null: если компонент React без состояния был упакован.

Хотя shallowWrapper.html() будет изначально null, действительно.

В исходном коде есть ошибка, она должна быть this.state.loaded, а не this.loaded:

MyComponent extends React.Component {
  state = { loaded: false };

  componentDidMount() {
    this.props.fetchData.then(() => {
          this.setState({ loaded: true });
    });
  }

  methodThatIWantToTest() {
      //do some stuff here
  }

  render() {
      if (this.state.loaded) {
          return <p>hi</p>;
      } else {
          return null;
      }
  }
}

componentDidMount и methodThatIWantToTest желательно рассматривать как разные единицы. Они относятся к разным тестам. Если в перехватчиках жизненного цикла вызывается methodThatIWantToTest, в тесте componentDidMount может быть задано значение:

   it('should fetch data', async () => {
      const props = { fetchData: Promise.resolve('data') };
      const shallowWrapper = shallow(<MyComponent {...props}/>);
      expect(shallowWrapper.html()).toBe(null);
      await props.fetchData;
      expect(shallowWrapper.html()).toBe('<p>hi</p>');
   });

Тогда метод можно протестировать отдельно. Крючки жизненного цикла можно отключить, чтобы уменьшить количество движущихся частей:

   it('should do some stuff', () => {
      const shallowWrapper = shallow(<MyComponent {...props}/>, {disableLifecycleMethods: true});
      const result = shallowWrapper.instance().methodThatIWantToTest();
      expect(result).toBe(...);    
   });
0 голосов
/ 25 августа 2018

Вот рабочий пример:


myComponent.js

import * as React from 'react';

export default class MyComponent extends React.Component {

  constructor(...props) {
    super(...props);
    this.state = { loaded: false };
  }

  componentDidMount() {
    this.props.fetchData().then(() =>
      this.setState({ loaded: true })
    );
  }

  methodThatIWantToTest() {
    return 'result';
  }

  render() {
    if (this.state.loaded) {
      return <div>loaded</div>;
    } else {
      return null;
    }
  }
}

myComponent.test.js

import * as React from 'react';
import { shallow } from 'enzyme';

import MyComponent from './myComponent';

describe('myComponent', () => {
  it('should do some stuff', async () => {
    const fetchData = jest.fn(() => Promise.resolve());
    const props = { fetchData };

    const shallowWrapper = shallow(<MyComponent {...props}/>);
    expect(shallowWrapper.html()).toBe(null);

    expect(shallowWrapper.instance().methodThatIWantToTest()).toBe('result');

    // pause the test and let the event loop cycle so the callback
    // queued by then() within componentDidMount can run
    await Promise.resolve();

    expect(shallowWrapper.html()).toBe('<div>loaded</div>');
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...