为了账号安全,请及时绑定邮箱和手机立即绑定

假计时器不会在 Jest 中正确触发 setTimeout 调用

假计时器不会在 Jest 中正确触发 setTimeout 调用

暮色呼如 2023-07-06 19:44:29
我有一个简单的 React UI-less 组件,用于显示传递操作的状态。有 4 种状态 - 待处理、正在运行、已完成、失败。这里的主要问题是运行和完成状态必须至少持续一段时间(例如 2 秒)。我正在尝试使用 Jest (26.6.3) 及其假计时器来测试此行为,但我无法让它工作。组件代码:export const TaskState = {    PENDING: "pending",    RUNNING: "running",    FINISHED: "finished",    FAILED: "failed",};export default function Task({ action, minDelay = 2000, children }) {    const [state, setState] = useState(TaskState.PENDING);    const [error, setError] = useState(null);    const timeoutHandle = useRef(null);    useEffect(() => {        return () => {            if (timeoutHandle.current) {                clearTimeout(timeoutHandle.current);            }        };    }, []);    const resetState = () => {        setState(TaskState.PENDING);        setError(null);    };    const onSuccess = () => {        setState(TaskState.FINISHED);        timeoutHandle.current = setTimeout(resetState, minDelay);    };    const onError = errMsg => {        setState(TaskState.FAILED);        setError(errMsg);    };    const startAction = () => {        setState(TaskState.RUNNING);        const start = performance.now();        let err = null;        try {            action();        } catch (e) {            err = e.message;        } finally {            const end = performance.now();            const elapsedTime = end - start;            const delayTime = minDelay - elapsedTime;            if (elapsedTime < minDelay && minDelay > 0) {                timeoutHandle.current = setTimeout(() => {                    err ? onError(err) : onSuccess();                }, delayTime);            } else {                err ? onError(err) : onSuccess();            }        }    };    return children({        state,        error,        startAction,    });}Task.propTypes = {    action: PropTypes.func.isRequired,    minDelay: PropTypes.number,    children: PropTypes.func.isRequired,};调用操作回调,执行从挂起到运行的状态转换,但不执行从运行到失败的下一个状态转换。当我手动测试它时它有效。最小示例 - https://codesandbox.io/s/heuristic-khorana-7vygv?file=/src/App.js
查看完整描述

1 回答

?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

在全局窗口对象上正确调用 setTimeout 解决了该问题。这在实际应用程序中并不重要,但对于专门修补 window.setTimeout 和其他函数的 jest 假定时器来说很重要。



查看完整回答
反对 回复 2023-07-06
  • 1 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信