2017-11-09 10 views
0

私はカウンタと呼ばれる単一の状態値を持つ単純なReact Parentコンポーネントを持っています。親コンポーネントの下には、親を呼び出して状態を更新するonClickハンドラを持つボタンである単一の子コンポーネントがあります。その後、テスト非同期呼び出しでJest問題に反応します

import React, { Component } from 'react'; 
import axios from 'axios' 

class Parent extends Component { 
    state = {counter: 0} 

    onClickAsync =() => { 
    console.log("Async Button clicked") 
    axios.get(`https://api.github.com/users/smitp33`) 
     .then(resp => { 
      this.setState(prevState => ({ 
      counter: prevState.counter + 1 
      })) 
     } 
    ) 
    } 

    render() { 
    return (
     <div> 
     <Child onClick={this.onClickAsync} action="Click"/> 
     </div> 
    ); 
    } 
} 

class Child extends Component { 

    render() { 
    return (
     <button onClick={this.props.onClick}>{this.props.action}</button> 
    ) 
    } 
} 

export default Parent 

...:私はシミュレートするために、以下の非同期更新にコードを変更した場合

import React from 'react'; 
import {mount, shallow} from 'enzyme'; 
import Parent from '../Problem'; 

it('handles Click event',() => { 

    const wrapper = mount(<Parent />) 
    expect(wrapper.state().counter).toEqual(0) 
    console.log(wrapper.debug()) 
    const button = wrapper.find('button').at(0); 
    button.simulate('click'); 
    expect(wrapper.state().counter).toEqual(1) 
    console.log(wrapper.state().counter) 

}); 

import React, { Component } from 'react'; 
import axios from 'axios' 

class Parent extends Component { 
    state = {counter: 0} 

    onClick =() => { 
    console.log("Button clicked") 
    this.setState(prevState => ({ 
     counter: prevState.counter + 1 
    })) 
    } 

    render() { 
    return (
     <div> 
     <Child onClick={this.onClick} action="Click"/> 
     </div> 
    ); 
    } 
} 

class Child extends Component { 

    render() { 
    return (
     <button onClick={this.props.onClick}>{this.props.action}</button> 
    ) 
    } 
} 

export default Parent 

これは、次のテストで冗談を用いて微細なテスト同じテストが失敗するのは、カウンタが更新されていないように見えるからです。

handles Click event 

    expect(received).toEqual(expected) 

    Expected value to equal: 
     1 
    Received: 
     0 

     at Object.<anonymous>.it (src/__tests__/Problem.test.js:14:35) 
     at Promise.resolve.then.el (node_modules/p-map/index.js:46:16) 
     at process._tickCallback (internal/process/next_tick.js:109:7) 

私は状態が実際に変更されたことを証明するためにSETSTATE機能へのコールバックを追加して、それは間違いなく持っているので、私は問題は、単に非同期コンポーネントの呼び出しが完了する前に完了冗談テストの周りにあると信じています。

私はいろいろな記事とJestドキュメントを読んでいて、ここでテストしようとするとさまざまなことを試みましたが、これまで成功していませんでしたので、誰かがどのようにこれに近づくべきかについての明確な助言。次のように正確な依存関係に

詳細は以下のとおりです。

"dependencies": { 
    "axios": "^0.17.0", 
    "enzyme": "^3.1.0", 
    "enzyme-adapter-react-16": "^1.0.2", 
    "jest-enzyme": "^4.0.1", 
    "prop-types": "^15.6.0", 
    "react": "^16.0.0", 
    "react-circular-progressbar": "^0.5.0", 
    "react-dom": "^16.0.0", 
    "react-percentage-circle": "^1.1.3", 
    "react-scripts": "1.0.15" 
    } 

これは、すべてのバニラで行われ、次のsetupTests.jsで定義されていると「を作成反応するアプリ」セットアップ:

import Enzyme from "enzyme"; 
import 'jest-enzyme'; 
import Adapter from "enzyme-adapter-react-16"; 

Enzyme.configure({ adapter: new Adapter() }); 

global.requestAnimationFrame = function(callback) { 
    setTimeout(callback, 0); 
}; 

答えて

0

this.setStateは非同期で動作します。したがって、状態を設定してもすぐに更新されるわけではありません。 、あなたのテストで言ったことで

onClickAsync =() => { 
    console.log("Async Button clicked") 
    axios.get(`https://api.github.com/users/smitp33`) 
    .then(resp => { 
     this.setState({ 
     counter: this.state.counter + 1; 
     },() => { 
     console.log(this.state.counter); 
     }) 
    } 
    ) 
} 

を、任意のアサーションを行う前に終了する非同期操作を待つ:あなたのasync機能では、むしろこれを試してみてください。つまり、実際にアサーションを実行する場所である.then()メソッドを活用してください。

の代わりに私が孤立して機能をテストすることにしたシミュレーションの一環として、非同期クリックをテストする:私は次のようにこの作業を取得するために管理上方に設けられた詳細と

+0

感謝 - 私はSETSTATEへの呼び出しは、それゆえ私はあなたが述べまったく同じコールバックを使用してテストしていた即時ではないことを知っていました。興味深いことに、通常はコードを実行するとJestの内部で実行するとconsole.logの出力が表示されますが、そうでない場合はo)。あなたのヒントを使用して、私はここで重要なのは、Jestが喜んで対処するPromisesに依存することであることを認識しました。実際のPromiseを返す機能を変更する必要があります。 – smitp33

+0

はい一応です。 – brandNew

0

実際に何かを返すようにclickイベントを変更することで、この場合Promiseを使用して、asyncを適切に使用してテストで待つことができました。

修正コード:

onClickAsync =() => { 
    console.log("Async Button clicked") 
    return (
     axios.get(`https://api.github.com/users/smitp33`) 
      .then(resp => { 
       this.setState(prevState => ({ 
       counter: prevState.counter + 1 
       })) 
      } 
     ) 
    ) 
    } 

修正テストは:fshock

test('calls Async Click function', async() => { 
    const wrapper = mount(<Parent />) 
    console.log(wrapper.state().counter) 
    await wrapper.instance().onClickAsync() 
    console.log(wrapper.state().counter) 
    expect(wrapper.state().counter).toEqual(1) 
}); 
関連する問題