【问题标题】:How to test useRef with Jest and react-testing-library?如何使用 Jest 和 react-testing-library 测试 useRef?
【发布时间】:2020-03-22 18:33:17
【问题描述】:

我正在使用 create-react-app、Jest 和 react-testing-library 来配置聊天机器人项目。

我有一个使用 useRef 挂钩的功能组件。当有新消息出现时,会触发 useEffect 挂钩并通过查看 ref 的当前属性来引发滚动事件。

const ChatBot = () => {
  const chatBotMessagesRef = useRef(null)
  const chatBotContext = useContext(ChatBotContext)
  const { chat, typing } = chatBotContext

  useEffect(() => {
    if (typeof chatMessagesRef.current.scrollTo !== 'undefined' && chat && chat.length > 0) { 
       chatBotMessagesRef.current.scrollTo({
         top: chatMessagesRef.current.scrollHeight,
         behavior: 'smooth'
       })
    }
    // eslint-disable-next-line
  }, [chat, typing])

   return (
    <>
      <ChatBotHeader />
      <div className='chatbot' ref={chatBotMessagesRef}>
        {chat && chat.map((message, index) => {
          return <ChatBotBoard answers={message.answers} key={index} currentIndex={index + 1} />
        })}
        {typing &&
        <ServerMessage message='' typing isLiveChat={false} />
        }
      </div>
    </>
  )
}

我想测试一下当有新的聊天项目或输入时是否触发了scrollTo功能,你有什么想法吗?我找不到测试 useRef 的方法。

【问题讨论】:

  • 你可以模拟 scrollTo 函数(使用 jest.fn()),添加一个新的聊天项目并检查是否调用了模拟。
  • 但是 scrollTo 函数是当前对象的实例,它是 ref 的方法,如何在不模拟 ref 的情况下模拟 scrollTo?
  • 啊,是的,这可能很困难,您是否尝试过使用以下方法模拟它:Element.prototype.scrollTo = jest.fn()
  • 我试过了,但是如何在渲染之前对元素做出反应?我需要在渲染之前以某种方式模拟 ref 以便我可以测试它,我猜这是一个非常奇怪的情况,我也使用了 jest.spyOn 但这也不起作用

标签: reactjs jestjs react-testing-library


【解决方案1】:

您可以将您的 useEffect 移出您的组件,并将 ref 作为参数传递给它。类似的东西

const useScrollTo = (chatMessagesRef, chat) => {
    useEffect(() => {
    if (typeof chatMessagesRef.current.scrollTo !== 'undefined' && chat && chat.length > 0) { 
       chatBotMessagesRef.current.scrollTo({
         top: chatMessagesRef.current.scrollHeight,
         behavior: 'smooth'
       })
    }
  }, [chat])
}

现在在你的组件中

import useScrollTo from '../..'; // whatever is your path

const MyComponent = () => {
  const chatBotMessagesRef = useRef(null);
  const { chat } = useContext(ChatBotContext);

  useScrollTo(chatBotMessagesRef, chat);

  // your render..
}

你的 useScrollTo 测试:

import useScrollTo from '../..'; // whatever is your path
import { renderHook } from '@testing-library/react-hooks'

it('should scroll', () => {
  const ref = {
    current: {
      scrollTo: jest.fn()
    }
  }
  const chat = ['message1', 'message2']

  renderHook(() => useScrollTo(ref, chat)) 

  expect(ref.current.scrollTo).toHaveBeenCalledTimes(1)
})

【讨论】:

  • 如果我通过使用 const ref = React.createRef() 创建一个 ref 作为道具,它会给我错误,但如果我像 const 一样模拟它ref = { current: {scrollTo: jest.fn() }} 并给出一个模拟聊天数组而不是从真实的上下文对象中获取它,测试有效,而且似乎我涵盖了所有条件ChatBot 组件使用 useScrollTo 钩子,所以你的回答有点让我纠正我的测试!
  • 谢谢,非常实用的方法,对我很有帮助:)
猜你喜欢
  • 2020-05-14
  • 2021-02-11
  • 2021-02-28
  • 1970-01-01
  • 1970-01-01
  • 2020-03-24
  • 2020-01-20
  • 1970-01-01
相关资源
最近更新 更多