测试自定义钩子,其中 useEffect 应该被多次调用。

huangapple go评论59阅读模式
英文:

Testing a custom hook where useEffect should be invoked multiple times

问题

我正在尝试测试一个自定义的React钩子,其中包含useEffect,并且我希望在测试中获得对它的引用,因为我必须多次调用它来测试其行为。这涉及到简单的节流:

在测试中,我有一个基本的场景:

但是我想要一个对内部的useEffect的引用,以便能够多次调用并检查回调函数。此外,一个定时器可以触发并检查行为。对于这方面的任何建议将不胜感激!

英文:

I'm trying to test a custom React hook, where i have useEffect inside, and I want a reference to it in the tests as I have to call it multiple times to test the behavior. It's about simple throttling:

export const useThrottleEffect = (effect, deps = [], delay) => {
    const lastCall = useRef(0);

    useEffect(() => {
        const now = new Date().getTime();
        if (now - lastCall.current > delay) {
            effect();
            lastCall.current = now;
        }
    }, [...deps, delay]);
}

in the test, I have a basic scenario:

    let callback;

    beforeEach(() => {
        callback = jest.fn();
    });

    test("useThrottleEffect()", () => {
        const {result} = renderHook(() => useThrottleEffect(callback, [Date.now()], 1000));
        expect(callback).toHaveBeenCalledTimes(1);
        result; //?
        expect(result.current).toBeUndefined();
    });
});

But I what a reference to the inside useEffect in terms to be able to call multiple times and check the callback. Furthermore, a timer could tick and check the behavior. Any tips here would be highly appreciated!

答案1

得分: 1

import { render } from '@testing-library/react';

const Util = ({ number, cb }) => {
  useThrottleEffect(cb, [], 2500);

  return number;
}

describe('useThrottleEffect', () => {
  beforeAll(() => {
    jest.useFakeTimers();
  });

  it('should work', () => {
    const cb = jest.fn();

    const { rerender } = render(<Util cb={cb} number={1} />);

    jest.advanceTimersByTime(1000);
    rerender(<Util cb={cb} number={2} />);

    jest.advanceTimersByTime(1000);
    rerender(<Util cb={cb} number={3} />);

    jest.advanceTimersByTime(1000);
    rerender(<Util cb={cb} number={4} />);

    expect(cb).toHaveBeenCalledTimes(2);
  });
}

references:


<details>
<summary>英文:</summary>

You can create an utility component in your test, using the hook as intended to be used in your application.

solution outline (not tested):

```jsx
import { render } from &#39;@testing-library/react&#39;

const Util = ({ number, cb }) =&gt; {
  useThrottleEffect(cb, [], 2500)

  return number
}

describe(&#39;useThrottleEffect&#39;, () =&gt; {
  beforeAll(() =&gt; {
    jest.useFakeTimers()
  })

  it(&#39;should work&#39;, () =&gt; {
    const cb = jest.fn()

    const { rerender } = render(&lt;Util cb={cb} number={1} /&gt;)

    jest.advanceTimersByTime(1000)
    rerender(&lt;Util cb={cb} number={2} /&gt;)

    jest.advanceTimersByTime(1000)
    rerender(&lt;Util cb={cb} number={3} /&gt;)

    jest.advanceTimersByTime(1000)
    rerender(&lt;Util cb={cb} number={4} /&gt;)

    expect(cb).toHaveBeenCalledTimes(2)
  })
})

references:

huangapple
  • 本文由 发表于 2023年2月27日 17:59:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/75578998.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定