2016-05-24 7 views
5
  • を呼び出す関数を呼び出す
  • v15.1.0を反応させるの冗談v12.1.1
  • 酵素V2.3.0

私がしようとしていますクリックによって呼び出される関数で約束を呼び出すコンポーネントをテストする方法を解説します。私はJestのrunAllTicks()機能が私をここで助けてくれることを期待していましたが、約束を果たしているようではありません。のリアクト冗談と酵素とのテストシミュレートクリックすると約束

コンポーネント:

import React from 'react'; 
import Promise from 'bluebird'; 

function doSomethingWithAPromise() { 
    return new Promise((resolve) => { 
    setTimeout(() => { 
     resolve(); 
    }, 50); 
    }); 
} 

export default class AsyncTest extends React.Component { 
    constructor(props) { 
    super(props); 

    this.state = { 
     promiseText: '', 
     timeoutText: '' 
    }; 

    this.setTextWithPromise = this.setTextWithPromise.bind(this); 
    this.setTextWithTimeout = this.setTextWithTimeout.bind(this); 
    } 

    setTextWithPromise() { 
    return doSomethingWithAPromise() 
     .then(() => { 
     this.setState({ promiseText: 'there is text!' }); 
     }); 
    } 

    setTextWithTimeout() { 
    setTimeout(() => { 
     this.setState({ timeoutText: 'there is text!' }); 
    }, 50); 
    } 

    render() { 
    return (
     <div> 
     <div id="promiseText">{this.state.promiseText}</div> 
     <button id="promiseBtn" onClick={this.setTextWithPromise}>Promise</button> 
     <div id="timeoutText">{this.state.timeoutText}</div> 
     <button id="timeoutBtn" onClick={this.setTextWithTimeout}>Timeout</button> 
     </div> 
    ); 
    } 
} 

やテスト:

import AsyncTest from '../async'; 
import { shallow } from 'enzyme'; 
import React from 'react'; 

jest.unmock('../async'); 

describe('async-test.js',() => { 
    let wrapper; 

    beforeEach(() => { 
    wrapper = shallow(<AsyncTest />); 
    }); 

    // FAIL 
    it('displays the promise text after click of the button',() => { 
    wrapper.find('#promiseBtn').simulate('click'); 

    jest.runAllTicks(); 
    jest.runAllTimers(); 

    wrapper.update(); 

    expect(wrapper.find('#promiseText').text()).toEqual('there is text!'); 
    }); 

    // PASS 
    it('displays the timeout text after click of the button',() => { 
    wrapper.find('#timeoutBtn').simulate('click'); 

    jest.runAllTimers(); 

    wrapper.update(); 

    expect(wrapper.find('#timeoutText').text()).toEqual('there is text!'); 
    }); 
}); 
+0

代わりに、doSomethingWithAPromise関数をAsyncTestコンポーネントの小道具として渡して、テスト内でモックできます。http://stackoverflow.com/questions/38308214/react-enzyme-test-componentdidmount-async-call/40875174 #40875174 – bodrin

答えて

1

何とかテストを終了する前に満たすために約束を待つ必要が周りに多くはありません。私が見ることができるあなたのコードからそれを行う2つの主な方法があります。

  1. onClickとあなたの約束方法を個別にテストします。したがって、onClickが正しい機能を呼び出すが、setTextWithPromiseを覗いて、クリックを誘発してsetTextWithPromiseが呼び出されたことをアサートすることを確認する。次に、コンポーネントインスタンスを取得し、そのメソッドを呼び出して、ハンドラをアタッチして正しいことをアサーションするという約束を返すこともできます。

  2. 約束が解決したときに呼び出されるコールバック小道具が公開されています。私は成功し、次の要素を組み合わせることで、この問題を解決してきました

17

  • モックアウトの約束と、それは次の目盛りまでのテストを延期するために、すぐに
  • 利用ノードのsetImmediateを解決します、約束が解決される時です。
  • Jestのdoneを呼び出して、非同期でテストを終了します。 - 設計によって約束は、それらが作成されるのと同じダニに解決することはありませんので、

    global.doSomethingWithAPromise =() => Promise.resolve({}); 
    
    it('displays the promise text after click of the button', (done) => { 
        wrapper.find('#promiseBtn').simulate('click'); 
    
        setImmediate(() => { 
        expect(wrapper.find('#promiseText').text()).toEqual('there is text!'); 
        done(); 
        }) 
    }); 
    

    酵素のupdate()が、十分でも、この方法を使用するときに必要でもありません。このようになりますあなたの例では

、 。ここで何が起こっているかについての詳細な説明は、this questionを参照してください。

+0

ビンゴ! 'setImmediate'は、私のコンポーネントの' componentDidUpdate'ライフサイクルメソッドの一つによってトリガされていたコールバック関数で使用する必要がありました。 –

+0

私は同様の問題がありましたが、 'setTimeout(()=> {...}、0)'で解決しました。 'setImmediate'という何らかの理由で、' yarn test'コマンドでさえ突発的にテストが失敗するようになりました。 – Ernesto

関連する問題