如何使用 Jest 和 react-testing-library 测试 useRef?
Posted
技术标签:
【中文标题】如何使用 Jest 和 react-testing-library 测试 useRef?【英文标题】:How to test useRef with Jest and react-testing-library? 【发布时间】: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 但这也不起作用 【参考方案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 钩子,所以你的回答有点让我纠正我的测试! 谢谢,非常实用的方法,对我很有帮助:)以上是关于如何使用 Jest 和 react-testing-library 测试 useRef?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jest.mock 模拟 useRef 和反应测试库
如何在 TypeScript 中使用 Jest 和 Knex 进行测试?