Cara menguji komponen kelas dalam bereaksi

9

Saya mencoba beberapa unit pengujian, saya membuat kotak pasir dengan contoh palsu https://codesandbox.io/s/wizardly-hooks-32w6l (pada kenyataannya saya memiliki formulir)

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { number: 0 };    
  }

  handleSubmit = (number1, number2) => {
    this.setState({ number: this.handleMultiply(number1, number2) })
  }

  handleMultiply = (number1, number2) => {
    return number1 * number2
  }

  render() {
    const { number } = this.state;

    return (
      <div className="App">
        <form onSubmit={e => this.handleSubmit(3, 7)}>       
          <input type="submit" name="Submit" value="Multiply" />
        </form>
        <Table number={number} />
      </div>
    );
  }
}

export default App;

Jadi ide awal saya adalah mencoba menguji fungsi multiplikasi. Dan melakukan ini, yang jelas tidak berhasil

import App from "../src/App";

test("Multiply", function() {
  const expected = 21;
  const result = App.handleMultiply(3, 7);
  expect(result).toBe(expected);
});

saya mendapat

_App.default.handleMultiply bukan fungsi

Apakah pendekatan saya benar? Jika ya lalu bagaimana cara menguji fungsi? Selain itu, haruskah saya menguji dari sudut pandang pengguna alih-alih untuk fungsi internal (ini yang saya baca)? Haruskah saya menguji output di layar (saya pikir ini tidak masuk akal)?

pengguna3808307
sumber
2
Anda mendekati ini dengan pola pikir yang salah. Alih-alih memicu formulir kirim lalu periksa untuk memastikan negara telah diperbarui dengan tepat termasuk logika multiply.
Alexander Staroselsky
@AlexanderStaroselsky ok, terima kasih, saya akan mencoba, dan melakukan pertanyaan yang lebih spesifik jika saya macet
user3808307
@AlexanderStaroselsky bagaimana jika formulir di komponen anak dan menyerahkan penangan di induk? Apakah saya perlu melakukan tes integrasi di sana?
user3808307
1
Ini mungkin masalah pendapat tapi saya pasti akan menguji ini secara terpisah. Tes untuk anak adalah bahwa pada pengiriman itu memicu fungsi lulus dari orangtua melalui alat peraga kemudian juga untuk menguji bahwa negara membuat seperti yang Anda harapkan. Untuk orang tua, saya akan memicu acara dan memastikan negara telah diperbarui dengan benar.
Alexander Staroselsky
@AlexanderStaroselsky Terima kasih
user3808307

Jawaban:

4

Anda dapat menggunakan metode instance ()enzyme untuk mendapatkan instance React Component. Kemudian, panggil handleMultiplymetode secara langsung dan buat pernyataan untuk itu. Selanjutnya, jika handleMultiplymetode ini memiliki efek samping atau perhitungan yang sangat rumit, Anda perlu membuat nilai pengembalian yang diejek sederhana untuknya. Ini akan membuat lingkungan uji terisolasi untuk handleSubmitmetode. Ini berarti handleSubmitmetode tidak akan tergantung pada nilai balik dari implementasi nyata handleMultiplymetode.

Misalnya

app.jsx:

import React from 'react';
import { Table } from './table';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { number: 0 };
  }

  handleSubmit = (number1, number2) => {
    this.setState({ number: this.handleMultiply(number1, number2) });
  };

  handleMultiply = (number1, number2) => {
    return number1 * number2;
  };

  render() {
    const { number } = this.state;

    return (
      <div className="App">
        <form onSubmit={(e) => this.handleSubmit(3, 7)}>
          <input type="submit" name="Submit" value="Multiply" />
        </form>
        <Table number={number} />
      </div>
    );
  }
}

export default App;

table.jsx:

import React from 'react';

export const Table = ({ number: num }) => {
  return <div>table: {num}</div>;
};

app.test.jsx:

import App from './app';
import { shallow } from 'enzyme';

describe('59796928', () => {
  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<App></App>);
  });
  describe('#handleSubmit', () => {
    it('should pass', () => {
      expect(wrapper.exists()).toBeTruthy();
      wrapper.find('form').simulate('submit');
      expect(wrapper.state()).toEqual({ number: 21 });
    });
  });
  describe('#handleMultiply', () => {
    it('should pass', () => {
      const comp = wrapper.instance();
      const actual = comp.handleMultiply(2, 10);
      expect(actual).toBe(20);
    });
  });
});

Hasil tes unit dengan laporan cakupan:

 PASS  src/stackoverflow/59796928/app.test.jsx (11.688s)
  59796928
    #handleSubmit
       should pass (16ms)
    #handleMultiply
       should pass (9ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    90.48 |      100 |    85.71 |    94.44 |                   |
 app.jsx   |      100 |      100 |      100 |      100 |                   |
 table.jsx |       50 |      100 |        0 |    66.67 |                 4 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        13.936s

Kode sumber: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59796928

slideshowp2
sumber
Bagaimana jika formulir itu dalam komponen anak? Bagaimana saya memicu handleSubmit dalam ujian, selain itu dengan formulir yang dikirimkan? Terima kasih
user3808307