测试自定义挂钩 - 未包含在行为警告中

Mic*_*ite 4 testing react-hooks react-custom-hooks

我尝试测试自定义挂钩,但收到此警告消息

console.error node_modules/@testing-library/react-hooks/lib/core/console.js:19
    Warning: An update to TestComponent inside a test was not wrapped in act(...).
    
    When testing, code that causes React state updates should be wrapped into act(...):
    
    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */
    
    This ensures that you're testing the behavior the user would see in the browser. 
Run Code Online (Sandbox Code Playgroud)

这是我的自定义钩子

import { useState, useEffect } from 'react'

import io from 'socket.io-client'

import config from './../../../../config'

const useNotificationsSocket = (user) => {
  const [socket, setSocket] = useState(null)
  const [numUnreadMessages, setNumUnreadMessages] = useState(0)

  const configureSocket = socket => {
    socket.on('connect', () => {
      const data = {
        user: user,
      }
      socket.emit('user joined', data)
    })

    socket && socket.on('messages updated', (data) => {
      //console.log(data)
      setNumUnreadMessages(data.numUnreadMessages)
    })
  }

  useEffect(() => {
    const fetchSocket = async () => {
      const s = await io(config.nSocket.url, {transports: ['websocket']})
      configureSocket(s)
      setSocket(s)
    }

    // Check that user is not an empty object as this causes a crash.
    user && user.Id && fetchSocket()
  }, [user])

  return [socket, numUnreadMessages]
}

export { useNotificationsSocket }
Run Code Online (Sandbox Code Playgroud)

这是测试

import { renderHook, act } from '@testing-library/react-hooks'

import { useNotificationsSocket } from './../hooks/useNotificationsSocket'

jest.mock('socket.io-client')

describe('useNotificationsSocket', () => {
  it('returns a socket and numUnreadMessages', async () => {
    const user = { Id: '1' }
    const { result } = renderHook(() => useNotificationsSocket(user))
    expect(result).not.toBeNull()
  })
})
Run Code Online (Sandbox Code Playgroud)

我已经尝试导入 act 并将代码包装在对 act 的调用中,但是尽管我尝试包装代码,但我仍然收到警告,并且无法弄清楚在这种情况下应该如何使用 act 。

Jas*_*ark 11

你的钩子是异步的,所以你需要等待它的响应:

describe('useNotificationsSocket', () => {
  it('returns a socket and numUnreadMessages', async () => {
    const user = { Id: '1' }
    const { result } = renderHook(() => useNotificationsSocket(user))
    await waitFor(() => expect(result).not.toBeNull())
  })
})
Run Code Online (Sandbox Code Playgroud)

此外,如果您定义了多个测试,并且无法卸载挂钩,则可能会遇到原始错误。至少这似乎是@testing-library/reactv13.3.0 中的行为。您可以通过在测试完成时卸载挂钩来解决此问题:

describe('useNotificationsSocket', () => {
  it('returns a socket and numUnreadMessages', async () => {
    const user = { Id: '1' }
    const { result, unmount } = renderHook(() => useNotificationsSocket(user))
    await waitFor(() => expect(result).not.toBeNull())
    unmount()
  })
})
Run Code Online (Sandbox Code Playgroud)