react-hooks-testing-library 的作者在这里。
TL;DR;你不能解构result.current 并让get 接收更新的值。
这个问题很多,所以我会花一些时间为遇到这个问题的人提供更详细的答案。
首先,在您的示例中,resolved 测试通过了,因为waitFor 返回一个承诺,您必须通过await 才能看到失败:
// ...
await waitFor(() => {
expect(get).toStrictEqual({
data1: 1,
data2: 2,
data3: 3
});
});
// ...
在这种情况下,等待期望通过会超时,因为值永远不会改变。
所以真正的问题是为什么在调用set 时不更新get(顺便说一句...state 在本例中更合适)?
好吧,让我们看看这段代码:
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(或result.setState)将成功更新result.state,但没有指向state变量的链接,因此值不会改变。
因此,通过拥有const { result: { current: [get, set] } } = renderHook(...),您还将get 锁定为result.current 的初始值,而不是setting 的数量将允许更新新变量,因为它与@987654343 的连接@ 已丢失。
最后,我认为这是一个常见的意外,尤其是在使用来自钩子的元组结果时(例如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
});
});
// ...
无论如何,希望能解决问题并祝测试愉快!