javascript 在没有“act”错误的异步函数的中间状态上Assert

r6vfmomb  于 2022-12-21  发布在  Java
关注(0)|答案(1)|浏览(102)

我有一个loading状态,以及一个循环该状态的函数,在状态之间获取和设置数据:

async function getData(fetch) {
  setLoading(true);
  setData(await fetch());
  setLoading(false);
}

使用await act()将等待状态稳定,这意味着对loading === true的任何Assert都将失败。

it('cycles loading',async () => {
   // ... renderHook
   await act(getData)
   await waitFor(() => expect(result.current.loading).toBe(true)) // This always fails
   await waitFor(() => expect(result.current.data).toBe(newData)) // This passes
   await waitFor(() => expect(result.current.loading).toBe(false))// This passes
}

让它工作的一个方法是不使用act()

it('cycles loading',await () => {
   // ... renderHook
   getData(); // Gives act warning
   await waitFor(() => expect(result.current.loading).toBe(true)) // This passes
   await waitFor(() => expect(result.current.data).toBe(newData)) // This passes
   await waitFor(() => expect(result.current.loading).toBe(false))// This passes
}

我试着使用promises,同时将call包含在一个act中,并在act中Assert:

it('cycles loading',async () => {
   // ... renderHook
   let resolve;
   const fetch = () => new Promise(res => {resolve = res})
   await act(() => {
     getData();
     waitFor(() => expect(result.current.loading).toBe(true)) // This passes
     resolve(newData);
   }  
   await waitFor(() => expect(result.current.data).toBe(newData)) // This passes
   await waitFor(() => expect(result.current.loading).toBe(false))// This passes
   // Still getting act error...
}

这些测试在语义上是100%正确的,但是它们代表了我试图让这种类型的测试工作的迭代。

预过帐编辑

在又尝试了一次迭代之后,我让它工作了,但是我不知道为什么,这是一个工作的版本,任何关于为什么的见解都将非常感谢。
我所做的是将承诺的分辨率从act()中移除

it('cycles loading',async () => {
   // ... renderHook
   let resolve;
   const fetch = () => new Promise(res => {resolve = res})
   await act(() => {
     getData();
     waitFor(() => expect(result.current.loading).toBe(true)) // This passes
   }
   resolve(newData);
   await waitFor(() => expect(result.current.data).toBe(newData)) // This passes
   await waitFor(() => expect(result.current.loading).toBe(false))// This passes
}
gojuced7

gojuced71#

您的getData实现在异步与同步处理逻辑方面存在缺陷。
应该这样做:

async function getData(fetch) {    
    setLoading(true);
    return fetch().finally(() => {
        setLoading(false);
    });
}

然后你所有的测试都变得简单了,你只需要等待一个承诺,仅此而已。而且拒绝不会影响状态。

相关问题