如何用两个useEffect语句测试钩子?

时间:2019-07-18 11:57:33

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

我有以下钩子:


const useBar = () => {
  const [myFoo, setFoo] = useState(0);
  const [myBar, setBar] = useState(0);
  useEffect(() => {
    setFoo(myFoo + 1);
    console.log("setting foo (1)", myFoo, myBar);
  }, [setFoo, myFoo, myBar]);
  useEffect(() => {
    setBar(myBar + 1);
    console.log("setting bar (2)", myFoo, myBar);
  }, [setBar, myBar, myFoo]);
};

使用组件时,我具有无限循环的预期行为:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const Bar = () => {
  useBar();
  return <div>Bar</div>;
};

function App() {
  return (
    <Bar />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

从console.log中:

setting foo (1) 1 1
setting bar (2) 1 1
setting foo (1) 2 2
setting bar (2) 2 2
setting foo (1) 3 3
setting bar (2) 3 3
...

但是用@testing-library/react-hooks进行测试只能给出第一个循环输出:

describe("Tests", () => {
  test("useBar", async () => {
    const { rerender } = renderHook(() => {
      return useBar();
    });

    // await waitForNextUpdate();
    // tried the above doesn't work

    // rerender(); 
    // with rerender it loops through the next "cycle"
  });

});

想知道如何正确地测试钩子,而无需调用rerender并模仿与React相同的行为-在状态更改时重新呈现组件。

1 个答案:

答案 0 :(得分:1)

我猜您想测试使用hook的{​​{1}}并在发生无限循环时报告错误。 但是实际上我们无法测试无限循环,只能设置次数限制。当循环超过此限制时,我们认为它将继续无限循环。至于是否实际上是无限循环,则不容易证明。

但是,测试重复useEffect并不容易。 尽管使用useEffect可能会发生超时错误,但该错误也可能是由于长时间的异步操作而引起的,作为单元测试,您需要快速的反馈。您不能每次都等待超时。这是浪费时间。

感谢这个问题,我找到了方向。Provide a way to trigger useEffect from tests

当我将waitForNextUpdate替换为useEffect时,我可以快速而准确地收到useLayoutEffect错误。这仅需要在所需测试中将Maximum update depth exceeded替换为useEffect。循环无限时,测试将失败。

Edit Test useEffect infinite loop

useLayoutEffect