web-dev-qa-db-ja.com

JestとEnzymeを使用して、history.Pushを含む反応イベントハンドラーを単体テストする方法は?

単純なコンポーネントが与えられた場合:

export default class SearchForm extends Component {
  constructor(props) {
    super(props)
    this.state = { query: '' }
  }
  onSubmit = (event) => {
    event.preventDefault()
    history.Push(`/results/${this.state.query}`, { query: this.state.query })
  }
  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <input
          type="text"
          value={this.state.query}
          onChange={event => this.setState({ query: event.target.value })}
        />
        <button>Search</button>
      </form>
    )
  }
}

そしてテスト:

describe('SearchForm Component', () => {
  it('should navigate to results/query when submitted', () => {
    const wrapper = shallow(<SearchForm />)
    ...?
  })
})

フォーム送信により、ユーザーが正しいクエリ値で次のページに移動していることをどのように確認しますか?

OnSubmitハンドラーを単純にモックし、少なくとも呼び出されたことを確認しようとしましたが、これによりhistory.Push

const wrapper = shallow(<SearchForm />)
const mockedEvent = { target: {}, preventDefault: () => {} }
const spy = jest.spyOn(wrapper.instance(), 'onSubmit')
wrapper.find('form').simulate('submit', mockedEvent)
expect(spy).toHaveBeenCalled()
10
Darryl Snow

それは実際には簡単です。テスト内でコンポーネントを浅くレンダリングする場合、次のように、コンポーネントに任意の小道具を渡すことができます。
const wrapper = shallow(<SearchForm history={historyMock} />)

ところで、onSubmitの中では、this.props.history.Push(...)のように呼び出す必要があります。

ここで、モックを作成するために(詳細は documentation にあります)、テストで次のように記述できます。
const historyMock = { Push: jest.fn() };

実際にはPushオブジェクトのhistoryメソッドのみをモックしていることに注意してください。コンポーネント内でさらにメソッドを使用してテストする場合は、テストする各モックを作成する必要があります。

そして、Pushモックが正しく呼び出されたことをアサートする必要があります。それを行うには、必要なアサーションを記述します。
expect(historyMock.Push.mock.calls[0]).toEqual([ (url string), (state object) ]);
必要な(url string)および(state object)アサートされる。

18
rodgobbi