反応でクラスコンポーネントをテストする方法


9

私はいくつかのユニットテストを試みています、私は偽の例でサンドボックスを作成しましたhttps://codesandbox.io/s/wizardly-hooks-32w6l(実際にはフォームがあります)

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;

したがって、私の最初のアイデアは、乗算関数をテストしようとすることでした。そして、これは明らかに機能しませんでした

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

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

私は得る

_App.default.handleMultiplyは関数ではありません

私のアプローチは正しいですか?はいの場合、機能をテストするにはどうすればよいですか?そうでない場合、内部関数ではなくユーザーの視点からテストする必要がありますか(これは私が読んだものです)?画面上の出力をテストする必要がありますか(これは妥当ではないと思います)?


2
あなたは間違った考え方でこれに取り組んでいます。代わりにフォーム送信をトリガーしてから、乗算ロジックを含めて状態が適切に更新されていることを確認してください。
Alexander Staroselsky

ありがとう、私がしようとします、と私は動けなくなる場合は、より具体的な質問を行い、[OK]を@AlexanderStaroselsky
user3808307

@AlexanderStaroselsky子コンポーネントのフォームと親の送信ハンドラの場合はどうなりますか?そこで統合テストを行う必要がありますか?
user3808307

1
それは意見の問題かもしれませんが、私は間違いなくこれらを個別にテストします。子のテストでは、送信時に親から小道具を介して渡された関数をトリガーし、期待どおりに状態がレンダリングされることをテストします。親の場合、イベントをトリガーして、状態が正しく更新されていることを確認します。
アレクサンダースタロスキー

@AlexanderStaroselskyありがとう
user3808307

回答:


4

instance()メソッドを使用してenzyme、React Componentのインスタンスを取得できます。次に、handleMultiplyメソッドを直接呼び出して、アサーションを作成します。さらに、handleMultiplyメソッドに副作用や非常に複雑な計算がある場合は、単純な模擬戻り値を作成する必要があります。handleSubmitメソッドのための隔離されたテスト環境を作成します。つまり、handleSubmitメソッドはメソッドの実際の実装の戻り値に依存しませんhandleMultiply

例えば

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

カバレッジレポートを使用した単体テストの結果:

 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

ソースコード:https : //github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59796928


フォームが子コンポーネントにあった場合はどうなりますか?テストでhandleSubmitをどのようにトリガーしますか、それ以外はフォーム送信でトリガーしますか?ありがとう
user3808307
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.