Jest.js React useEffect钩子在测试中无限运行

58wvjzkj  于 2023-10-14  发布在  Jest
关注(0)|答案(2)|浏览(141)

我这里有一个NextJS 13的代码片段

export default function Members() {
  // States
  const [users, setUsers] = useState<MemberType[]>([]);
  const [loading, setLoading] = useState(false);
  const searchParams = useSearchParams();
  // To refresh the page
  const router = useRouter();
  const inputRef = useRef<HTMLInputElement | null>(null);

  // Function to fetch a book
  const fetchBooks = async (userQuery: string | null) => {
    if (!userQuery) {
      const res = await fetch("/api/users/members", {
        method: "GET",
        headers: { "Content-Type": "application/json" },
      });
      const body: MemberType[] = await res.json();
      return body;
    }
    const res = await fetch(`/api/users/members/${userQuery}`, {
      method: "GET",
      headers: { "Content-Type": "application/json" },
    });
    const body: MemberType[] = await res.json();
    return body;
  };

  // Runs if the search parameters change
  useEffect(() => {
    setLoading(true);
    const searched = searchParams.get("search");
    console.log(searched);
    
    fetchBooks(searched).then((users) => {
      setUsers(users);
      setLoading(false);
    });
    if (searched && inputRef.current) {
      inputRef.current.value = searched;
    }
  }, [searchParams]);
  //...

我正在使用Jest测试Members函数。
在测试文件中,

jest.mock("next/navigation", () => ({
  useRouter: () => ({
    push: jest.fn(),
  }),
  useSearchParams: () => ({
    get: jest.fn().mockReturnValue(''),
  }),
}));

这个简单的测试

describe("Members page", () => {
  it("should render the page correctly", async () => {
    await act(async () => {
      render(<Members />);
      
    });
  });
});

然而,测试超时,看起来useEffect钩子正在无限地运行。我怀疑这与mock中的get函数有关,它再次触发了useEffect钩子。我一直在寻找,如果有任何方式来改变这一模拟?

4dc9hkyq

4dc9hkyq1#

我相信只听你真正需要的字段变化会更安全,在你的例子中是search,特别是当它是一个 * 原始字符串 * 时。

const searched = searchParams.get("search"); // move outside useEffect

useEffect(() => {
    setLoading(true);
    console.log(searched);
    
    fetchBooks(searched).then((users) => {
      setUsers(users);
      setLoading(false);
    });

    if (searched && inputRef.current) {
      inputRef.current.value = searched;
    }
}, [searched]); // call only when "searched" changes
d6kp6zgx

d6kp6zgx2#

每次调用useSearchParams时都返回一个新对象
请改为执行以下操作:

jest.mock("next/navigation", () => {
  const searchParams = {
    get: jest.fn().mockReturnValue(""),
  };
  return {
    useRouter: () => ({
      push: jest.fn(),
    }),
    useSearchParams: () => searchParams,
  };
});

相关问题