Component.js
_import React from 'react'
import request from 'superagent'
export default React.createClass({
getInitialState() {
return {cats: []}
},
componentDidMount() {
request('/api', (err, res) => {
if (err) return;
this.setState({
cats: res.body.results
})
})
},
render() {
let cats = this.state.cats
let catsList = (
<ul>
{cats.map((c) => <li key={c.id}>cat</li>)}
</ul>
)
return (
<div>
{cats.length ? catsList : null}
</div>
)
}
})
_
Component.test.js
_jest.unmock('../app.js')
jest.unmock('superagent')
import React from 'react'
import {mount} from 'enzyme'
import nock from 'nock'
import App from '../app.js'
describe('App', () => {
let ajaxFn
beforeEach(() => {
ajaxFn = nock('http://localhost')
.get('/api')
.reply(200, {
results: [{id: 1}, {id: 2}, {id: 3}]
})
})
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
expect(wrapper.state('cats').length).toBe(3)
})
})
_
テストに合格しません。 wrapper.state('cats').length
は常に_0
_です。
setState
が状態をすぐに更新することを保証しないことを理解していますが、コンポーネントに「cats」を記録すると、更新されていることがわかります。
酵素が認識していないコンテキストでコンポーネントに状態を設定することになった場合、レンダリングツリーの更新バージョンを取得するには、ラッパーで.update()
を手動で呼び出す必要があります。
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
expect(wrapper.update().state('cats').length).toBe(3)
})
同様の問題があり、it
コールバックからpromiseを返し、promiseのthen
メソッドで期待値を確認する必要がありました。
あなたの場合(ajaxFnが約束だったと仮定するか、それを1つに変えることができると仮定して)、これはおおよそ次のようになると思います。
it('renders correct number of cats', () => {
let wrapper = mount(<App />)
return ajaxFn.then(() => {
expect(wrapper.state('cats').length).toBe(3);
}
})
使用しているすべてのライブラリに精通しているわけではありませんが、コードが非同期で実行されているため、状態を更新する前にテストが終了しています。テストにasync/awaitを追加することで、この問題を解決することができました。
it('renders correct number of cats', async () => {
let wrapper = await mount(<App />)
expect(wrapper.state('cats').length).toBe(3)
})