1

子入力コンポーネントのレンダリングを担当する App コンポーネントがあります。また、 というメソッドを介して Twitch API へのフェッチ要求を処理する役割もありますchannelSearch。React で ajax/fetch を操作するために、ここで概説されている推奨されるベスト プラクティスを順守しようとしました。

メソッドは props を介して渡され、コールバックを介して呼び出されます。

fetch メソッドは実際には isomorphic-fetch であることに注意してください。

channelSearch (searchReq, baseUrl="https://api.twitch.tv/kraken/channels/") {
  fetch(baseUrl + searchReq)
  .then(response => {
    return response.json();
  })
  .then(json => {
    this.setState({newChannel:json});
  })
  .then( () => {
    if (!("error" in this.state.newChannel) && this.channelChecker(this.state.newChannel._id, this.state.channelList) ) {
      this.setState(
        {channelList: this.state.channelList.concat([this.state.newChannel])}
      );
    }
  })
  .catch(error => {
    return error;
  });
}

channelSearch現在、メソッドのテストを作成しようとしています。現在、DOM のコンポーネントmount全体に酵素と jsdom を使用しています。<App>コールバックで子ノードを見つけ、クリックをシミュレートし (コールバックを起動する必要があります)、コンポーネントの状態が変更されたかどうかを確認します。ただし、これは機能しないようです。

メソッドを直接呼び出してみましたが、this.state未定義の問題が発生しました。

test('channel search method should change newChannel state', t => {
  const wrapper = mount(React.createElement(App));

  wrapper.find('input').get(0).value = "test";
  console.log(wrapper.find('input').get(0).value);
  wrapper.find('input').simulate("change");

  wrapper.find('button').simulate("click");

  console.log(wrapper.state(["newChannel"]));


});

私は本当に道に迷いました。メソッド自体の記述が不十分なのか、それともジョブに適切なツールを使用していないのかわかりません。どんなガイダンスでも大歓迎です。

更新 #1:

コメントで推奨されているようにnockを含めました。テストは次のようになります。

test('channel search method should change newChannel state', t => {
  // Test object setup

  var twitch = nock('https://api.twitch.tv')
                .log(console.log)
                .get('/kraken/channels/test')
                .reply(200, {
                  _id: '001',
                  name: 'test',
                  game: 'testGame'
                });

  function checker() {
    if(twitch.isDone()) {
      console.log("Done!");
      console.log(wrapper.state(["newChannel"]));
    }
    else {
      checker();
    }
  }

  const wrapper = mount(React.createElement(App));
  wrapper.find('input').get(0).value = "test";
  wrapper.find('input').simulate("change");
  wrapper.find('button').simulate("click");

  checker();
});

これはまだコンポーネントの状態を変更していないようです。

4

3 に答える 3

1

フェッチは非同期ですが、同期的にテストしています。同期モックでフェッチをモックするか、テストを非同期にする必要があります。

ノックはここであなたのために働くかもしれません。

于 2016-04-21T15:21:40.240 に答える
0

I suggest you create a sample of your test using plnkr.

I agree with Tom that you're testing synchronously. It would of course be helpful to show off your actual component code (all of the relevant portions, like what calls channelSearch, or at the least describe it by saying e.g. "channelSearch is called by componentDidMount()". You said:

I run into problems with this.state being undefined.

This is because this.setState() is asynchronous. This is for performance reasons, so that React can batch changes.

I suspect you'll need to change your code that is currently:

.then(json => {
    this.setState({newChannel:json});
})

to:

.then(json => {
  return new Promise(function(resolve, reject) {
    this.setState({newChannel:json}, resolve);
  })
})

Note that your checker() method won't work. It's looping, but twitch.isDone() will never be true because it never has a chance to run. Javascript is single threaded, so your checker code will run continuously, not allowing anything else in between.

If you set up the plnkr, I'll take a look.

于 2016-06-01T05:39:03.577 に答える