Reactjs 组件DIDMOUNT中使用的设置状态值未反映在酶测试中

Reactjs 组件DIDMOUNT中使用的设置状态值未反映在酶测试中,reactjs,jestjs,enzyme,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

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>
        )
    }
})
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)
    })
})
从“React”导入React
“超级代理”的导入请求
导出默认的React.createClass({
getInitialState(){
返回{cats:[]}
},
componentDidMount(){
请求('/api',(err,res)=>{
如果(错误)返回;
这是我的国家({
猫:res.body.results
})
})
},
render(){
let cats=this.state.cats
让catsList=(
    {cats.map((c)=>
  • cat
  • )}
) 返回( {cats.length?catsList:null} ) } })
Component.test.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>
        )
    }
})
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)
    })
})
jest.unmack('../app.js')
开玩笑地说,unmack(“超级代理”)
从“React”导入React
从“酶”导入{mount}
从“nock”导入nock
从“../App.js”导入应用程序
描述('App',()=>{
让ajaxFn
在每个之前(()=>{
ajaxFn=nock('http://localhost')
.get(“/api”)
.答复(200{
结果:[{id:1},{id:2},{id:3}]
})
})
它('呈现正确数量的猫',()=>{
让wrapper=mount()
expect(wrapper.state('cats').length).toBe(3)
})
})
考试不及格<代码>包装器。状态('cats')。长度始终为
0

我知道
setState
不能保证立即更新状态,
但是,如果我在组件中记录“cats”,我可以看到它正在更新。

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

it('renders correct number of cats', () => {
    let wrapper = mount(<App />)
    expect(wrapper.update().state('cats').length).toBe(3)
})
it('呈现正确数量的猫',()=>{
让wrapper=mount()
expect(wrapper.update().state('cats').length).toBe(3)
})

我有一个类似的问题,需要从
it
回调返回承诺,并检查承诺的
then
方法中的期望值

在您的情况下(假设ajaxFn是一个承诺,或者您可以将其变成一个承诺),我认为这大约是:

it('renders correct number of cats', () => {
    let wrapper = mount(<App />) 
    return ajaxFn.then(() => {
        expect(wrapper.state('cats').length).toBe(3);
    }
})
it('呈现正确数量的猫',()=>{
让wrapper=mount()
返回ajaxFn。然后(()=>{
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)
})
it('呈现正确数量的猫',异步()=>{
让包装器=等待装载()
expect(wrapper.state('cats').length).toBe(3)
})

这对我来说很有效,但我想知道为什么它不会因为setState而更新,包装器是否会遍历渲染树的副本或其他什么?Leland,在执行包装器。update()之前,您不需要首先确保状态更新已经发生吗或者我们依赖于nock ed ajaxFn是同步的这一事实,我在这里发布了一个答案。它可能与Simon Hardman的答案相似。谢谢,先生,我不知道
挂载
是一个异步函数!