Reactjs 在测试呈现获取的API数据的React组件时,如何最好地在做出任何断言之前等待该数据?

Reactjs 在测试呈现获取的API数据的React组件时,如何最好地在做出任何断言之前等待该数据?,reactjs,jestjs,axios,react-hooks,enzyme,Reactjs,Jestjs,Axios,React Hooks,Enzyme,我有一个简单的“编辑用户”组件,其中包含一个带有“名字”字段的表单。当组件首次呈现时,该字段为空,直到用户数据的API请求完成。获取数据后,状态将更新,组件将重新呈现,这次将填充“First Name”字段。(需要明确的是,发生这种情况不需要用户交互。) 我的测试要求正确填充“First Name”字段,但目前正在失败,因为它只测试组件的初始呈现,然后才能获取用户信息 测试这种行为的有效方法是什么,即等待(模拟的)请求完成后再进行断言 FWIW,我用的是React 16.12.0 以下是缩写组件

我有一个简单的“编辑用户”组件,其中包含一个带有“名字”字段的表单。当组件首次呈现时,该字段为空,直到用户数据的API请求完成。获取数据后,状态将更新,组件将重新呈现,这次将填充“First Name”字段。(需要明确的是,发生这种情况不需要用户交互。)

我的测试要求正确填充“First Name”字段,但目前正在失败,因为它只测试组件的初始呈现,然后才能获取用户信息

测试这种行为的有效方法是什么,即等待(模拟的)请求完成后再进行断言

FWIW,我用的是React 16.12.0

以下是缩写组件:

import React, { useState, useEffect } from 'react'
import axios from 'axios'

const EditUser = (props) => {
  const [user, setUser] = useState({
    fname: "",
    lname: ""
  })

  const fetchUser = async () => {
    await axios.get(`/api/users/${props.userId}`)
    .then(response => {
      const data = response.data
      const user = {
        fname: data.attributes.fname,
        lname: data.attributes.lname
      }
      setUser(user)
    })
    .catch(error => console.log(error))
  }

  useEffect(() => {
    fetchUser()
  }, [])

  return (
    <div>
      <h2>Edit User</h2>
      <form>
        <div className="form-group">
          <label>First Name</label>
          <input
            name="fname"
            value={user.fname}
          />
        </div>
      </form>
    </div>
  )
}

export default EditUser
import React,{useState,useffect}来自“React”
从“axios”导入axios
const EditUser=(道具)=>{
const[user,setUser]=useState({
fname:“”,
名称:“
})
const fetchUser=async()=>{
等待axios.get(`/api/users/${props.userId}`)
。然后(响应=>{
const data=response.data
常量用户={
fname:data.attributes.fname,
lname:data.attributes.lname
}
设置用户(用户)
})
.catch(错误=>console.log(错误))
}
useffect(()=>{
fetchUser()
}, [])
返回(
编辑用户
名字
)
}
导出默认编辑用户
以及测试:

import React from 'react'
import { mount } from 'enzyme'
import { act } from 'react-dom/test-utils'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import EditUser from 'packs/editUser'

describe('editUser', () => {
  let wrapper
  const axiosMock = new MockAdapter(axios)

  axiosMock.onGet('/api/users/5').reply(200, {
    id: 5,
    attributes: {
      fname: 'Bradley',
      lname: 'King'
    }
  })

  it('shows the user edit form', async () => {
    await act(async () => {
      wrapper = await mount(<EditUser userId={5} />)
    })

    const firstNameInput = wrapper.find('input[name="fname"]')

    // the following FAILS because the first name input is blank
    // _until_ the user data is fetched and the component is
    // re-rendered with field populated
    expect(firstNameInput.props().value).toEqual('Bradley')
  })
})
从“React”导入React
从“酶”导入{mount}
从“react dom/test utils”导入{act}
从“axios”导入axios
从“axios模拟适配器”导入模拟适配器
从“packs/EditUser”导入EditUser
描述('editUser',()=>{
让包装器
const axiosMock=新的MockAdapter(axios)
axiosMock.onGet('/api/users/5')。答复(200{
id:5,
属性:{
fname:“布拉德利”,
名字:“国王”
}
})
它('显示用户编辑表单',异步()=>{
等待动作(异步()=>{
包装器=等待装载()
})
const firstNameInput=wrapper.find('input[name=“fname”]”)
//以下操作失败,因为名字输入为空
//_u直到u获取用户数据并且组件
//重新渲染并填充字段
expect(firstNameInput.props().value).toEqual('Bradley')
})
})

谢谢

由于您希望出现渲染,因此可以使用
包装器的方法来

将酶组分树快照与反应组分树同步。如果某个外部对象可能正在某处更新组件的状态,则在检查渲染输出之前运行该命令非常有用

it('显示用户编辑表单',async()=>{
等待动作(异步()=>{
包装器=等待装载()
})
wrapper.update();
const firstNameInput=wrapper.find('input[name=“fname”]”)
expect(firstNameInput.props().value).toEqual('Bradley')
})

你愿意接受不使用酶的答案吗?@Jackyef肯定!在这种情况下,我建议您考虑一下您的测试需求。它有易于使用的测试API。这里的一个例子是实用程序,它可以立即满足您的需要。我不确定是否将此作为一个答案,所以我现在将此作为一个注释。尝试在
常量firstNameInput之前添加
wrapper.update()
@GabrielePetrioli确实,这确实让它通过了。谢谢信不信由你,我在发布这篇文章之前尝试过使用
wrapper.update()
,但还是失败了。我现在意识到我一定在
await act()中调用了
update()
如果你想把你的评论作为回答,我很乐意接受。干杯