我有一个useEffect挂钩,它在安装组件时加载,如下所示:
useEffect(() => {
listFiles().then(keys => {
setKeys(keys)
console.log(keys)
}).catch(err => {
showFail(err.message)
})
}, [])
我正在尝试使用react testing-library来测试该功能,只需使用render函数即可:
beforeEach(() => {
render(<Dashboard />)
})
但是,当我运行任何可以解决诺言并设置状态的测试时:
jest.mock('../utils/storage', () => ({
listFiles: jest.fn(() => Promise.resolve([])),
}))
最后,我收到一条奇怪的警告消息,内容是使用act
来包装事件:
Warning: An update to Dashboard 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. Learn more at ..
in Dashboard
18 | useEffect(() => {
19 | listFiles().then(keys => {
> 20 | setKeys(keys)
| ^
21 | console.log(keys)
22 | }).catch(err => {
23 | showFail(err.message)
我曾尝试将渲染器包装在act
中,但似乎没有任何改变。
关于我在这里做错什么的任何建议吗?我应该以其他方式渲染吗?
提前谢谢!
答案 0 :(得分:2)
当您尝试在组件完成更新所有状态之前进行断言时,通常会发生此错误。
请注意,在listFiles
内部您正在呼叫setKeys(keys)
,并会更新状态。
您应await
将新密钥(或文件)显示在文档中:
expect(await findByText('some file name or key')).toBeInTheDocument();
// more asserts here
或者,您可以Demo调用该模拟程序(尽管我认为上面的选项更好)。
await waitFor(() => expect(listFilesMock).toHaveBeenCalled());
// more asserts here
React Testing库应该已经将以上方法包装在act
中,因此您不需要这样做
act()
是什么:编写UI测试时,可以将诸如渲染,用户事件或数据获取之类的任务视为与用户界面交互的“单元”。 React提供了一个名为act()的帮助程序,可以确保在进行任何断言之前,已经处理了与这些“单元”相关的所有更新并将其应用于DOM。
名称行为来自“排列行为声明”模式。
答案 1 :(得分:0)
就我而言,我没有嘲笑 useEffect 异步函数。
component.test.tsx:
df1 <- structure(list(Location = c("A", "B"),
Job1 = c(1L, 4L),
Job2 = c(2L, 5L),
Job3 = c(3L, 6L),
Total = 6:7),
class = "data.frame", row.names = c(NA, -2L))
df2 <- structure(list(Location = c("A", "B"),
Job2 = 0:1,
Job1 = c(1L, 4L),
Job3 = c(1L, 1L),
Total = c(2L, 6L)),
class = "data.frame", row.names = c(NA, -2L))
component.tsx:
test('Working useEffect hook', () => {
const dbCallMock = jest.fn(() => Promise.resolve())
render(<Tracks dbCallMock ={dbCallMock} />)
}