componentDidMount中使用的setState值未反映在酶测试中

时间:2016-03-10 21:30:06

标签: reactjs jestjs enzyme

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并不保证立即更新状态, 但是,如果我记录了猫的情况。在组件中,我可以看到它更新。

3 个答案:

答案 0 :(得分:9)

如果你最终在某个酶不知道的上下文中设置了组件中的状态,则必须在包装器上手动调用.update(),以便获取渲染树的更新版本

it('renders correct number of cats', () => {
    let wrapper = mount(<App />)
    expect(wrapper.update().state('cats').length).toBe(3)
})

答案 1 :(得分:2)

我遇到了类似的问题,有必要从it回调中返回一个承诺,并检查承诺的then方法中的期望。

在你的情况下(假设ajaxFn是一个承诺,或者你可以把它变成一个)我认为这将是近似的:

it('renders correct number of cats', () => {
    let wrapper = mount(<App />) 
    return ajaxFn.then(() => {
        expect(wrapper.state('cats').length).toBe(3);
    }
})

答案 2 :(得分:1)

我不熟悉您正在使用的所有库,但由于您的代码是异步执行的,因此测试在状态可以更新之前完成。我能够通过在测试中添加async / await来解决这个问题:

it('renders correct number of cats', async () => {
    let wrapper = await mount(<App />)
    expect(wrapper.state('cats').length).toBe(3)
})