【问题标题】:Testing Polling with React Hooks Testing Library使用 React Hooks 测试库测试轮询
【发布时间】:2021-01-06 17:21:58
【问题描述】:

我创建了一个名为 usePolling 的自定义 Hook,它接受一个在一段时间内轮询的函数(由间隔声明),该钩子工作正常,但现在我正在尝试对其进行测试...我收到警告:更新测试内部的 TestHook 没有包含在 act(...) 中。错误,我看了肯特关于测试异步钩子的视频,但是我正在努力让警告消失......但是测试通过了。

这句台词是在抱怨

} finally {
    > 67 |       setBusy(false);
         |       ^
      68 |     }

这是有道理的,因为这是一个状态变化......但是你会看到我的测试已经包含了所有的行为

这是我制作的 GIST > https://gist.github.com/FrancisLeigh/f62bb3c68d16e434019d4843c86e6cf6

提前谢谢你:slight_smile:

【问题讨论】:

  • 您需要更改您的测试,以便在请求触发后等待 current.busy 值设置回 false。
  • @Win 你能给我一些更深入的了解吗?我试过使用waitForValueToChange,但 atm 玩得不好。
  • 嗨弗朗西斯,我已经附上了答案,很抱歉回复晚了。

标签: reactjs react-hooks react-testing-library


【解决方案1】:

很抱歉,回复晚了,但我只设法检查了您的答案,并且通过强制创建一个 prop 来覆盖 axios,我发现上述解决方案有点 hacky,所以我在下面详细介绍了您的问题的可能解决方案。我没有根据您在下面发布的 git 链接来确定这一点,因为看起来可能会导致混乱。

我们使用 await waitFor 非常重要,以确保我们可以在调用 Promise 之前和之后侦听对 busy 所做的更新,这样它就不会触发 Warning: An update to TestHook inside a test was not wrapped in act(...) 警告。

我认为该消息对用户有点欺骗性,因为用户通常认为将所述问题包装在一个行为中会解决问题,但在这种情况下,问题实际上在于使用 setInterval 并且它能够更新状态。

希望我的解决方案对您有所帮助,并努力弃用 axiosOverrideProp

使用PollingHook.js

import * as React from 'react';
import requestAdaptor from './requestAdaptor';

export function usePollingHook(pollTimeMs = 2000) {
    const [busy, setBusy] = React.useState(false);
    const [isPolling, setPolling] = React.useState(false);
    const [data, setData] = React.useState(null);

    React.useEffect(() => {
        if (isPolling) {
            const poll = async () => {
                if (!busy) {
                    setBusy(true);
                    const resp = await requestAdaptor();
                    setBusy(false);
                    setData(resp);
                }
            };
            const interval = setInterval(poll, pollTimeMs);
            return () => clearInterval(interval);
        }

        return () => null;
    }, [isPolling, busy, setBusy, pollTimeMs]);

    return {
        data,
        busy,
        isPolling,
        setPolling,
    };
}

index.spec.js

import { act, renderHook } from '@testing-library/react-hooks';
import { usePollingHook } from './usePollingHook';
import requestAdaptor from './requestAdaptor';

jest.useFakeTimers();
jest.mock('./requestAdaptor', () => jest.fn().mockResolvedValue(1));

describe('usePollingHook', () => {
    it('returns default props', () => {
        const { result } = renderHook(() => usePollingHook());

        expect(result.current.data).toEqual(null);
        expect(result.current.busy).toEqual(false);
        expect(result.current.isPolling).toEqual(false);
        expect(result.current.setPolling).toEqual(expect.any(Function));
    });

    it('ensures the state is updated when the hook has polled a request', async (done) => {
        const { result, waitFor } = renderHook(() => usePollingHook());

        expect(result.current.busy).toEqual(false);

        act(() => {
            result.current.setPolling(true);
        });

        await waitFor(() => expect(result.current.isPolling).toEqual(true));

        act(() => {
            jest.advanceTimersByTime(10000);
        });

        await waitFor(() => expect(result.current.busy).toEqual(true));
        expect(requestAdaptor).toBeCalled();
        await waitFor(() => expect(result.current.busy).toEqual(false));
        expect(result.current.data).toEqual(1);
        done();
    });
});

requestAdaptor.js

一些伪造的 http 函数,它会包装一个承诺,例如模拟axios或者fetch

export function requestAdaptor() {
    return new Promise((resolve) => {
        return setTimeout(() => {
            return resolve({ userId: 1 });
        }, 1000);
    });
}

export default requestAdaptor;

【讨论】:

  • 非常感谢您的跟进 :-) 我设法通过完全模拟我的钩子来解决我的问题,因为异步状态更新导致 Jest 出错,所以最好只模拟返回的方法来自我的 useAxios 钩子。谢谢你的工作:-)
【解决方案2】:

通过接受 axiosOverride 属性,我设法使钩子在测试时更可靠,然后我显然可以更轻松地控制和断言。

任何感兴趣的人> https://gist.github.com/FrancisLeigh/f62bb3c68d16e434019d4843c86e6cf6

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2020-08-13
    • 2021-07-29
    • 2021-07-03
    • 2020-12-28
    • 1970-01-01
    • 2020-11-01
    • 2020-05-23
    • 2020-06-14
    相关资源
    最近更新 更多