如何测试使用 Context 和 useEffect 的 React.js 页面?

Posted

技术标签:

【中文标题】如何测试使用 Context 和 useEffect 的 React.js 页面?【英文标题】:How to test React.js page that uses Context and useEffect? 【发布时间】:2022-01-07 14:43:03 【问题描述】:

我在使用 Jest 和测试库测试具有 Context 和 useEffect 的页面时遇到问题,您能帮帮我吗?

回购:https://github.com/jefferson1104/padawan

我的上下文:src/context/personContext.tsx

import  createContext, ReactNode, useState  from 'react'
import  useRouter  from 'next/router'

import  api  from '../services/api'

type PersonData = 
  name?: string
  avatar?: string


type PersonProviderProps = 
  children: ReactNode


type PersonContextData = 
  person: PersonData
  loading: boolean
  handlePerson: () => void


export const PersonContext = createContext( as PersonContextData)

export function PersonProvider( children : PersonProviderProps) 
  const [person, setPerson] = useState<PersonData>()
  const [loading, setLoading] = useState(false)
  const router = useRouter()

  function checkAvatar(name: string): string 
    return name === 'Darth Vader'
      ? '/img/darth-vader.png'
      : '/img/luke-skywalker.png'
  

  async function handlePerson() 
    setLoading(true)
    const promise1 = api.get('/1')
    const promise2 = api.get('/4')

    Promise.race([promise1, promise2]).then(function (values) 
      const data = 
        name: values.data.name,
        avatar: checkAvatar(values.data.name)
      

      setPerson(data)
      setLoading(false)
      router.push('/battlefield')
    )
  

  return (
    <PersonContext.Provider value= person, handlePerson, loading >
      children
    </PersonContext.Provider>
  )

我的页面:src/pages/battlefield.tsx

import  useContext, useEffect  from 'react'
import  useRouter  from 'next/router'

import  PersonContext  from '../context/personContext'
import Person from '../components/Person'

const Battlefield = () => 
  const  person  = useContext(PersonContext)
  const router = useRouter()

  useEffect(() => 
    if (!person.name) 
      router.push('/')
    
  )

  return <Person />


export default Battlefield

我的测试:src/tests/pages/Battlefield.spec.tsx

import  render, screen  from '@testing-library/react'

import  PersonContext  from '../../context/personContext'
import Battlefield from '../../pages'

jest.mock('../../components/Person', () => 
  return 
    __esModule: true,
    default: function mock() 
      return <div data-test-id="person" />
    
  
)

describe('Battlefield page', () => 
  it('renders correctly', () => 
    const mockPerson =  name: 'Darth Vader', avatar: 'darth-vader.png' 
    const mockHandlePerson = jest.fn()
    const mockLoading = false

    render(
      <PersonContext.Provider
        value=
          person: mockPerson,
          handlePerson: mockHandlePerson,
          loading: mockLoading
        
      >
        <Battlefield />
      </PersonContext.Provider>
    )

    expect(screen.getByTestId('person')).toBeInTheDocument()
  )
)

打印屏幕错误 enter image description here

【问题讨论】:

您对 Person 组件的模拟似乎不成功,因为图像中的输出还显示了代码中未显示的内容。您能否确保 Person 被正确模拟或针对实际的 Person 组件编写此测试? 已解决,出现错误是因为我调用战地页面的路径没有绝对路径 【参考方案1】:

我找到了解决办法:

发生错误是因为我调用战地页面的路径没有绝对路径。

【讨论】:

以上是关于如何测试使用 Context 和 useEffect 的 React.js 页面?的主要内容,如果未能解决你的问题,请参考以下文章

包含 Context.Provider 和 Context.Consumer 的 React Context 测试组件

React JS:在 API 调用成功后获取上下文数据

如何对访问 Provider.of(context) 的小部件进行 Flutter 测试

如何在 Spring Boot 测试中加载仅添加命名组件的基本 Spring Application-Context?

如何单元测试自定义应用程序类?

Mockito Mocking Android Context PackageManager Exception