React docs から ReactJS コンポーネント (特定のユーザーの最新の要点 URL をレンダリングする) を取得しましたが、そのようなコンポーネントを単体テストするための最良の方法は何か疑問に思っていました:
目標は
- 分離してテストする (模擬 http 呼び出しを使用)
- 既存のテスト セットアップ (モカ) を使用する
- 物事をシンプルに保つ
- 最終的に、コンポーネントの http 呼び出しが成功すると、状態の変更によって再レンダリングがトリガーされ、アンカー要素が適切な URL でレンダリングされることを確認します。
テストしたいコンポーネントは次のとおりです。
import React from 'react'
import $ from 'jquery'
export default React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
fetch(this.props.source).then(function(response) {
return response.json()
}).then(function(json) {
this.setState({
username: json[0].owner.login,
lastGistUrl: json[0].html_url
});
}.bind(this)).catch(function(ex) {
console.log('parsing failed', ex)
})
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={ this.state.lastGistUrl}>here</a>.
</div>
);
}
});
そして、これが私の最初のテストの試みです:
import TestUtils from 'react-addons-test-utils'
import React from 'react'
import { expect } from 'chai'
import { findDOMNode } from 'react-dom'
import UserGist from '../assets/js/components/UserGistWithFetch'
import nock from 'nock'
describe('UserGistWithFetch', () => {
it('Displays the correct url', (done) => {
nock.disableNetConnect();
nock('https://api.github.com')
.get('/users/octocat/gists')
.reply(200, [{owner:"octocat",html_url:"https://gist.github.com/6cad326836d38bd3a7ae"}])
const gist = TestUtils.renderIntoDocument(<UserGist source="https://api.github.com/users/octocat/gists"/>)
let a = TestUtils.scryRenderedDOMComponentsWithTag(gist, 'a')[0]
expect(a.getAttribute('href')).to.be.equal("https://gist.github.com/6cad326836d38bd3a7ae")
done()
})
})
モック コールバックが実行される前にコンポーネントが最初にレンダリングされ、アンカーが正しくレンダリングされないため、このテストは明らかに失敗します。
モックされた http 呼び出しが戻る前にテストが失敗し、コンポーネントが再レンダリングされる機会がありません。
私が理解していることから、Mocha は (done()
関数を使用して) 非同期テストを行う方法を提供しますが、これを配置するためのフックがテストで見つかりません。
それを達成するために必要なツール/フレームワークは何ですか?