В чем разница между имитацией энзима в поверхностных и монтируемых обертках? - PullRequest
0 голосов
/ 31 мая 2018

Вот мой компонент:

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      value: 'foo'
    };
  }

  onChange = (e) => {
    this.setState({
      value: e.currentTarget.value
    });
  };

  render() {
    return (
      <div className="App">
        <input
          id="foo"
          value={this.state.value}
          onChange={this.onChange}
        />
      </div>
    );
  }
}

Вот мой тест:

import {shallow, mount} from 'enzyme';

it('fires onChange', () => {
  let wrapper = mount(<App />);

  wrapper.find('#foo').simulate('change', {currentTarget: {value: 'bar'}});

  expect(wrapper.state().value).toBe('bar');
  expect(wrapper.find('#foo').props().value).toBe('bar');
});

Тест в настоящее время не проходит:

Expected value to be (using ===):
  "bar"
Received:
  "foo"

Но если я изменю mountдо shallow, это проходит.Я не совсем уверен, почему, и я хотел бы знать, есть ли другие практические различия между мелкой и рендерингом монтирования.

1 Ответ

0 голосов
/ 31 мая 2018

Для фиксации теста вы можете попробовать:

import { mount } from 'enzyme';

it('fires onChange', () => {
  const wrapper = mount(<App />).find('#foo');

  expect(wrapper.props().value).toBe('foo');

  wrapper.props().onChange({ currentTarget: { value: 'bar' } });

  expect(wrapper.props().value).toBe('bar');
});

Для уточнения различий между мелкой, монтированной и рендеринговой энзимами

мелкой

Реальный модульный тест (изоляция, дети не отрисовываются)

Простое поверхностное

Вызовы:

  • конструктор
  • render

Shallow + setProps

Вызовы:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • рендер

Shallow + unmount

Вызовы:

  • componentWillUnmount

Mount

Единственный способ проверить componentDidMount и componentDidUpdate.Полный рендеринг, включая дочерние компоненты.Требуется DOM (jsdom, домино).Более во время исполнения.Если реакция включена до JSDOM, для этого могут потребоваться некоторые хитрости:

`require ('fbjs / lib / ExecutionEnvironment'). CanUseDOM = true;

Простое монтирование

Вызовы:

  • конструктор
  • рендер
  • componentDidMount

Mount + setProps

Вызовы:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • рендер
  • componentDidUpdate

Монтирование + отключение

Вызовы:

  • componentWillUnmount

Визуализация

только вызывает рендеринг, но рендерит всех дочерних элементов.

Итак, мое правило:

  • Всегда начинайте с мелкого
  • Если необходимо проверить componentDidMount или componentDidUpdate, используйте mount
  • Если вы хотите проверить жизненный цикл компонента и поведение детей, используйте mount
  • Если вы хотите проверить рендеринг дочерних элементовс меньшими накладными расходами, чем при монтировании, и вы не интересуетесь методами жизненного цикла, используйте render

Кажется, есть очень маленький вариант использования для рендера.Мне это нравится, потому что это кажется более быстрым, чем требование jsdom, но, как сказал @ljharb, мы не можем на самом деле протестировать внутренние компоненты React с этим.

Интересно, можно ли было бы эмулировать методы жизненного цикла с помощью метода render, как мелкого?Я был бы очень признателен, если бы вы могли дать мне варианты использования, которые вы используете для рендеринга внутри, или какие варианты использования вы видели в дикой природе.

Мне также любопытно узнать, почему мелкий не вызывает componentDidUpdate.

Слава идет к https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913 и https://github.com/airbnb/enzyme/issues/465#issuecomment-227697726 Это в основном копия комментария к проблеме

...