140 votes

Quand faut-il utiliser render et shallow dans les tests Enzyme / React ?

Avant de poster cette question, j'ai essayé de faire une recherche dans sqa stackexchange mais je n'ai trouvé aucun message sur le sujet de shallow et render là-bas, donc j'espère que quelqu'un pourra m'aider ici.

Quand dois-je utiliser shallow et render pour tester les composants react ? En me basant sur la documentation d'airbnb, j'ai formulé quelques opinions sur la différence entre les deux :

  1. Puisque shallow teste les composants en tant qu'unité Il doit donc être utilisé pour les composants "parents". (ex. Tableaux, Wrappers, etc.)

  2. Le rendu est destiné aux composants enfants.

La raison pour laquelle j'ai posé cette question est que j'ai du mal à savoir lequel je dois utiliser (bien que la documentation indique qu'ils sont très similaires).

Alors, comment savoir lequel utiliser dans un scénario spécifique ?

4 votes

La différence entre shallow() et mount() est que shallow() teste les composants isolément des composants enfants qu'ils rendent, tandis que mount()va plus loin et teste les enfants d'un composant. Pour shallow(), cela signifie que si le composant parent effectue le rendu d'un autre composant qui ne parvient pas à effectuer le rendu, alors un rendu shallow() sur le parent passera quand même.

206voto

4m1r Points 512

En fonction de l'enzyme docs :

mount(<Component />) pour le rendu complet du DOM est idéal pour les cas d'utilisation où vous avez des composants qui peuvent interagir avec des apis DOM, ou qui peuvent nécessiter le cycle de vie complet afin de tester complètement le composant (par exemple, componentDidMount, etc.).

vs.

shallow(<Component />) pour Shallow rendering est utile pour vous contraindre à tester un composant en tant qu'unité, et pour vous assurer que vos tests n'affirment pas indirectement le comportement des composants enfants.

vs.

render qui est utilisé pour rendre les composants réactifs à HTML statique et analyser la structure HTML qui en résulte.

Vous pouvez toujours voir les "nœuds" sous-jacents dans un rendu peu profond, ce qui vous permet, par exemple, de faire quelque chose comme cet exemple (un peu artificiel) en utilisant AVA en tant qu'exécutant de la spécification :

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));
});

Remarquez que rendu , accessoires de réglage y trouver des sélecteurs et même événements synthétiques sont tous supportés par le rendu superficiel, donc la plupart du temps vous pouvez simplement utiliser cela.

Mais, vous ne serez pas en mesure d'obtenir le cycle de vie complet du composant, donc si vous vous attendez à ce que des choses se passent dans componentDidMount, vous devriez utiliser mount(<Component />) ;

Ce test utilise Sinon pour espionner le composant 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();
});

Ce qui précède ne passera pas avec rendu peu profond o Rendu

render vous fournira uniquement le code html, ce qui vous permettra de faire ce genre de choses :

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

    // insert Test component here...

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

J'espère que cela vous aidera !

1 votes

Je ne comprends toujours pas à 100%, pourquoi les trois verbes apportent des méthodes différentes avec eux. Par exemple, on peut utiliser wrapper.getNode() dans shallow mais pas dans render. Y a-t-il des explications/liens/docs/blogs qui m'aident à comprendre tout cela ?

0 votes

@HenryZhu il devrait être clair d'après la documentation que le rendu est plus impliqué que le rendu superficiel, puisqu'il essaie en fait d'imiter l'arbre DOM pour ce nœud de composant particulier.

15 votes

La migration de l'enzyme de la v2 à la v3 a fait que les méthodes de cycle de vie sont activées par défaut dans shallow également. github.com/airbnb/enzyme/blob/master/docs/guides/

19voto

Shyam Kumar Points 92

La différence entre shallow() et mount() est que  shallow() teste les composants en les isolant des composants enfants qu'ils rendent, tandis que mount() va plus loin et teste les enfants d'un composant.

Pour la méthode shallow(), cela signifie que si le composant parent effectue le rendu d'un autre composant qui ne parvient pas à effectuer le rendu, le rendu de la méthode shallow() sur le parent réussira quand même.

2 votes

Quand je testais props pour un composant, dois-je utiliser shallow y mount ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X