Когда следует использовать render и shallow в тестах Enzyme / React?

98

перед тем, как опубликовать этот вопрос, я попытался выполнить поиск в sqa stackexchange, но я не нашел там сообщения о мелководье и рендеринге, поэтому я надеюсь, что кто-то может мне помочь здесь.

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

  1. Поскольку shallow тестирует компоненты как единое целое , его следует использовать для «родительских» компонентов. (например, таблицы, оболочки и т. д.)

  2. Рендер предназначен для дочерних компонентов.

Причина, по которой я задал этот вопрос, заключается в том, что мне трудно понять, какой из них я должен использовать (хотя в документации говорится, что они очень похожи)

Итак, как мне узнать, какой из них использовать в конкретном сценарии?

Cyval
источник
2
Разница между shallow () и mount () заключается в том, что shallow () тестирует компоненты отдельно от дочерних компонентов, которые они отображают, в то время как mount () идет глубже и проверяет дочерние компоненты компонента. Для shallow () это означает, что если родительский компонент визуализирует другой компонент, который не может быть отрисован, то рендеринг shallow () на родительском элементе все равно пройдет.
Шьям Кумар,

Ответы:

167

Согласно документации по ферментам :

mount(<Component />) для полного рендеринга DOM идеально подходит для случаев использования, когда у вас есть компоненты, которые могут взаимодействовать с API DOM или могут потребовать полного жизненного цикла для полного тестирования компонента (например, componentDidMount и т. д.)

vs.

shallow(<Component />) для поверхностного рендеринга полезно ограничить себя тестированием компонента как единицы и гарантировать, что ваши тесты не подтверждают косвенно поведение дочерних компонентов.

vs.

renderкоторый используется для визуализации компонентов реакции на статический HTML и анализа полученной структуры HTML.

Вы все еще можете видеть базовые «узлы» в неглубокой визуализации, поэтому, например, вы можете сделать что-то вроде этого (слегка надуманного) примера, используя AVA в качестве средства выполнения спецификации:

let wrapper = shallow(<TagBox />);

const props = {
    toggleValue: sinon.spy()
};

test('it should render two top level nodes', t => {
    t.is(wrapper.children().length, 2);
});

test('it should safely set all props and still render two nodes', t => {
    wrapper.setProps({...props});
    t.is(wrapper.children().length, 2);
});

test('it should call toggleValue when an x class is clicked', t => {
    wrapper.setProps({...props});
    wrapper.find('.x').last().simulate('click');
    t.true(props.toggleValue.calledWith(3));
});

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

Но вы не сможете получить полный жизненный цикл компонента, поэтому, если вы ожидаете, что что-то произойдет в componentDidMount, вы должны использовать mount(<Component />);

В этом тесте Sinon используется для наблюдения за компонентами.componentDidMount

test.only('mount calls componentDidMount', t => {

    class Test extends Component {
        constructor (props) {
            super(props);
        }
        componentDidMount() {
            console.log('componentDidMount!');
        }
        render () {
            return (
                <div />
            );
        }
    };

    const componentDidMount = sinon.spy(Test.prototype, 'componentDidMount');
    const wrapper = mount(<Test />);

    t.true(componentDidMount.calledOnce);

    componentDidMount.restore();
});

Вышеупомянутое не пройдет с мелким рендерингом или рендерингом.

render предоставит вам только html, так что вы все равно можете делать такие вещи:

test.only('render works', t => {

    // insert Test component here...

    const rendered = render(<Test />);
    const len = rendered.find('div').length;
    t.is(len, 1);
});

надеюсь это поможет!

4м1р
источник
1
Я до сих пор не понимаю, почему эти три глагола приносят с собой разные методы. Например, можно использовать wrapper.getNode () в поверхностном режиме, но не в рендере. какие-либо объяснения / ссылки / документы / блоги, которые помогут мне получить это вместе?
Paulquappe
@HenryZhu, из документации должно быть ясно, что рендеринг более сложен, чем неглубокий, поскольку он фактически пытается имитировать дерево DOM для этого конкретного узла компонента
AGE
12
Фермент миграция из v2 в v3 сделала методу жизненного цикла по умолчанию в неглубоком, а github.com/airbnb/enzyme/blob/master/docs/guides/...
Абхинав Singi
2
Хорошее дополнительное объяснение различий здесь github.com/airbnb/enzyme/issues/465#issuecomment-227697726 и здесь github.com/airbnb/enzyme/issues/465#issuecomment-229116418
Дмитрий Гончар
9

Разница между shallow () и mount () заключается в том, что shallow () тестирует компоненты отдельно от дочерних компонентов, которые они отображают, в то время как mount () идет глубже и проверяет дочерние компоненты компонента.

Для shallow () это означает, что если родительский компонент визуализирует другой компонент, который не может быть отрисован, то рендеринг shallow () на родительском элементе все равно пройдет.

Шьям Кумар
источник
Когда я буду тестировать propsкомпонент, следует ли мне использовать shallowи mount?
Менай Ала Эддин - Аладдин