【问题标题】:React + Jest: Test that setTimeOut didn't get calledReact + Jest:测试 setTimeOut 没有被调用
【发布时间】:2021-09-15 23:28:52
【问题描述】:

我目前在useEffect 中有一个setTimeOut,我可以使用以下方法对其进行测试:

jest.useFakeTimers();
jest.advanceTimersByTime(5000);

而且效果很好。但是,随着successMessage 的变化,setTimeout 会被触发几次。如何编写一个测试来检查 setTimeOut 仅在 successMessage 不是空字符串时被调用?

我正在使用 jest 和 react-testing-library。

这是我的反应代码。

enum HELPER_MESSAGES {
    SUCCESS = 'Congratulations you signed up!',
    ERROR = 'Email address invalid',
}

export function EmailCapture (): ReactElement {
    const [inputValue, setInputValue] = useState<string>('');
    const [errorMessage, setErrorMessage] = useState<string>('');
    const [successMessage, setSuccessMessage] = useState<string>('');

    function handleOnClick (): void {
        const EMAIL_REGEX: RegExp = /^[a-zA-Z0-9]+([-._][a-zA-Z0-9]+)*@([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*.)+\.+[a-zA-Z]{2,}$/;
        const isInputValid: boolean = EMAIL_REGEX.test(inputValue) && inputValue !== '';

        if (isInputValid) {
            setSuccessMessage(HELPER_MESSAGES.SUCCESS);
        } else {
            setErrorMessage(HELPER_MESSAGES.ERROR);
        }
    }

    useEffect((): () => void => {
        const resetAfterSuccessTimer: NodeJS.Timeout = setTimeout((): void => {
            setSuccessMessage('');
        }, 5000);

        return (): void => {
            clearTimeout(resetAfterSuccessTimer);
        };
    }, [successMessage]);

    function handleOnChange (e: ChangeEvent<HTMLInputElement>): void {
        setInputValue(e.target.value);
        setErrorMessage('');
        setSuccessMessage('');
    }

    return (
        <TextInput
            onChange={handleOnChange}
            error={errorMessage}
            success={successMessage}
            value={inputValue}
        />
    );
}

我正在关注 TDD,所以我希望编写一个测试,让我编写以下代码:

useEffect((): () => void => {
    let resetAfterSuccessTimer: NodeJS.Timeout;

    if (successMessage) {
        resetAfterSuccessTimer= setTimeout((): void => {
            setSuccessMessage('');
            setButtonText('Sign up!');
            console.log('sexy');
        }, 5000);
    }

    return (): void => {
        clearTimeout(resetAfterSuccessTimer);
    };
}, [successMessage]);

sexy 这个词应该只会让控制台记录一次。

【问题讨论】:

  • 实例化后,不应该被调用。在successMessage之后它应该被调用一次,因为它改变了successMessage它调用useEffect但它不调用setTimeout......我相信就是这样......
  • @Noriller 我不确定我是否理解

标签: reactjs jestjs settimeout use-effect react-testing-library


【解决方案1】:

根据他们的文档弄清楚:https://jestjs.io/docs/timer-mocks,您可以执行以下操作:

expect(setTimeout).not.toHaveBeenCalled();

当你想检查它是否被调用过一次时,你可以这样做:

expect(setTimeout).toHaveBeenCalledTimes(1);

注意:这是测试实现细节,因此请注意这一点。

【讨论】:

    猜你喜欢
    • 2021-09-20
    • 2019-10-08
    • 2019-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2018-03-24
    • 2023-03-06
    • 2020-05-22
    相关资源
    最近更新 更多