这里的作者react-hooks-testing-library
。
TL;博士; 您无法解构result.current
并get
收到更新的值。
这出现了很多,所以我会花一些时间为遇到这个问题的任何人提供更详细的答案。
首先,在您的示例中,resolved
测试通过,因为返回一个您必须看到失败waitFor
的承诺:await
// ...
await waitFor(() => {
expect(get).toStrictEqual({
data1: 1,
data2: 2,
data3: 3
});
});
// ...
在这种情况下,它会超时等待期望通过,因为值永远不会改变。
所以真正的问题是为什么不get
(奇怪的名字顺便说一句......state
在这个例子中更合适)在set
被调用时更新?
好吧,让我们看看这段代码:
const result = {
state: 0,
setState(newState: number) {
this.state = newState;
}
};
const { state, setState } = result;
setState(1);
expect(state).toBe(1); // fails
测试失败的原因与您的示例相同。你能看出为什么吗?
好吧,解构将的值result
锁定result.state
在一个名为 的新变量中,无论它当时是什么state
。调用setState
(or result.setState
) 将成功 update result.state
,但没有指向state
变量的链接,因此值不会改变。
因此,通过让const { result: { current: [get, set] } } = renderHook(...)
您也锁定hasget
的初始值result.current
而不是set
ting 的数量,这将允许更新新变量,因为它的连接result.current
已丢失。
最后,我认为这是一个常见的意外,尤其是在使用来自钩子的元组结果时(例如const [state, setState] = useState()
)。给出的常见原因是人们不喜欢在他们的测试中result.current[0]
提到它们。result.current[1]
我可以对此表示同情。
许多人没有意识到的另一件事是,值result.current
是您从renderHook
回调返回的任何内容,因此您可以通过将renderHook
调用更改为以下内容轻松获得命名良好的值:
// ...
const { result } = renderHook(() => {
const [get, set] = React.useState({
data1: 0,
data2: 0,
data3: 0
})
return { get, set }
});
act(() => {
result.current.set({ data1: 1, data2: 2, data3: 3 });
});
expect(result.current.get).toStrictEqual({
data1: 1,
data2: 2,
data3: 3
});
});
// ...
无论如何,希望清除它并进行愉快的测试!