Kapan Anda harus menggunakan render dan shallow dalam tes Enzim / React?

95

sebelum memposting pertanyaan ini, saya mencoba mencari di sqa stackexchange tetapi saya tidak menemukan posting tentang dangkal dan membuat di sana, jadi saya harap seseorang dapat membantu saya di sini.

Kapan saya harus menggunakan shallow dan render dalam pengujian komponen react? Berdasarkan dokumen airbnb, saya memberikan beberapa pendapat tentang perbedaan keduanya:

  1. Karena dangkal menguji komponen sebagai satu kesatuan , jadi itu harus digunakan untuk komponen 'induk'. (mis. Tabel, Pembungkus, dll.)

  2. Render untuk komponen anak.

Alasan saya mengajukan pertanyaan ini, adalah karena saya mengalami kesulitan untuk mencari tahu mana yang harus saya gunakan (meskipun dokumen mengatakan bahwa mereka sangat mirip)

Jadi, bagaimana saya tahu mana yang akan digunakan dalam skenario tertentu?

Cyval
sumber
2
Perbedaan antara shallow () dan mount () adalah bahwa shallow () menguji komponen secara terpisah dari komponen anak yang direndernya sementara mount () melangkah lebih dalam dan menguji anak komponen. Untuk shallow () ini berarti jika komponen induk merender komponen lain yang gagal dirender, rendering shallow () pada induk akan tetap lolos.
Shyam Kumar

Jawaban:

162

Sesuai dokumen Enzim :

mount(<Component />) untuk rendering DOM Penuh ideal untuk kasus penggunaan di mana Anda memiliki komponen yang mungkin berinteraksi dengan DOM apis, atau mungkin memerlukan siklus proses penuh untuk menguji komponen sepenuhnya (mis., componentDidMount dll.)

vs.

shallow(<Component />) untuk Perenderan dangkal berguna untuk membatasi diri Anda sendiri dalam menguji komponen sebagai unit, dan untuk memastikan bahwa pengujian Anda tidak secara tidak langsung menyatakan perilaku komponen turunan.

vs.

renderyang digunakan untuk membuat komponen react ke HTML statis dan menganalisis struktur HTML yang dihasilkan.

Anda masih dapat melihat "node" yang mendasari dalam render yang dangkal, jadi misalnya, Anda dapat melakukan sesuatu seperti ini (sedikit dibuat-buat) contoh menggunakan AVA sebagai runner spesifikasi:

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

Perhatikan bahwa rendering , pengaturan props, dan pencarian penyeleksi dan bahkan kejadian sintetis semuanya didukung oleh rendering yang dangkal, jadi seringkali Anda hanya dapat menggunakannya.

Tapi, Anda tidak akan bisa mendapatkan siklus hidup lengkap dari komponen, jadi jika Anda mengharapkan sesuatu terjadi di componentDidMount, Anda harus menggunakan mount(<Component />);

Tes ini menggunakan Sinon untuk memata-matai komponen tersebutcomponentDidMount

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

Di atas tidak akan lulus dengan dangkal render atau membuat

render akan memberi Anda html saja, jadi Anda masih dapat melakukan hal-hal seperti ini:

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

    // insert Test component here...

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

semoga ini membantu!

4m1r
sumber
1
saya masih belum mengerti 100%, mengapa ketiga kata kerja membawa metode yang berbeda dengannya. Misalnya, seseorang dapat menggunakan wrapper.getNode () di shallow tetapi tidak dalam render. ada penjelasan / link / docs / blog, yang membantu saya mendapatkan togehter ini?
Paulquappe
@HenryZhu harus jelas dari dokumen bahwa render lebih terlibat daripada dangkal, karena sebenarnya mencoba meniru pohon DOM untuk node komponen tertentu
USIA
11
migrasi enzim dari v2 ke v3 telah membuat metode siklus hidup aktif secara default di dangkal juga github.com/airbnb/enzyme/blob/master/docs/guides/…
Abhinav Singi
1
Penjelasan tambahan yang bagus tentang perbedaannya ada di sini github.com/airbnb/enzyme/issues/465#issuecomment-227697726 dan di sini github.com/airbnb/enzyme/issues/465#issuecomment-229116418
Dmitry Gonchar
9

Perbedaan antara shallow () dan mount () adalah bahwa shallow () menguji komponen secara terpisah dari komponen anak yang direndernya sementara mount () melangkah lebih dalam dan menguji anak komponen.

Untuk shallow () ini berarti jika komponen induk merender komponen lain yang gagal dirender, rendering shallow () pada induk akan tetap lolos.

Shyam Kumar
sumber