如何正确编写 Jest 测试以避免 act() 警告?
How correctly write Jest test for avoid act() warning?
useEffect 通常使用 Promises 更新状态。
此更新在开玩笑中引起长时间警告:Warning: An update to null inside a test was not wrapped in act(...).
这种情况如何正确编写 Jest 测试?
现场示例,可重现示例:
https://codesandbox.io/s/jest-test-for-useeffect-with-promises-spieq?file=/index.test.js
index.test.js
import React from "react";
import Hello from "./Hello";
import { create, act } from "react-test-renderer";
it("works", () => {
let root;
act(() => {
root = create(<Hello />);
});
// console.log("From test:", );
let repr = JSON.stringify(root.toJSON());
expect(repr).toBe('{"type":"span","props":{},"children":["Hello! "]}');
});
Hello.js
import React, { useState, useEffect } from "react";
export default () => {
const [count, setCount] = useState();
useEffect(() => {
Promise.resolve({}).then(() => setCount(4));
}, []);
return <span>Hello! {count}</span>;
};
更新 1:
提案之一的相同结果:
我建议你使用testing-library/react which could be use smoothly with jest and provide async methods
你的测试会变成这样:
import React from "react";
import Hello from "./Hello";
import { render } from '@testing-library/react';
it("works", () => {
const { baseElement } = render(<Hello />);
expect(baseElement).toBeTruthy();
});
编辑:为了完整起见,在您的示例中,您试图测试组件中的更新是否发生在使用承诺的效果之后。
为了 waitFor 一些异步你可以使用方法 findBy (findBy 方法是 getBy 查询和 waitFor 的组合。)
import React from "react";
import Hello from "./Hello";
import { render, findByText } from "@testing-library/react";
import "@testing-library/jest-dom";
it("works", async () => {
const { baseElement } = render(<Hello />);
expect(await findByText(baseElement, "Hello! 4")).toBeVisible();
});
让我解释一下,import "@testing-library/jest-dom"
允许您使用方法 toBeVisible
因此,此测试正在渲染一个组件 Hello,然后它在 baseElement(即组件本身)内等待(默认值 1000 毫秒)寻找文本“Hello!4”,如果找到,它将return找到的元素,我们要测试它是否可见。
看起来这个示例工作正常
import React from "react";
import Hello from "./Hello";
import { render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
it("works", () => {
render(<Hello />);
return waitFor(() => screen.getByText("Hello! 4"));
// expect(baseElement.toBeTruthy();
});
useEffect 通常使用 Promises 更新状态。
此更新在开玩笑中引起长时间警告:Warning: An update to null inside a test was not wrapped in act(...).
这种情况如何正确编写 Jest 测试?
现场示例,可重现示例:
https://codesandbox.io/s/jest-test-for-useeffect-with-promises-spieq?file=/index.test.js
index.test.js
import React from "react";
import Hello from "./Hello";
import { create, act } from "react-test-renderer";
it("works", () => {
let root;
act(() => {
root = create(<Hello />);
});
// console.log("From test:", );
let repr = JSON.stringify(root.toJSON());
expect(repr).toBe('{"type":"span","props":{},"children":["Hello! "]}');
});
Hello.js
import React, { useState, useEffect } from "react";
export default () => {
const [count, setCount] = useState();
useEffect(() => {
Promise.resolve({}).then(() => setCount(4));
}, []);
return <span>Hello! {count}</span>;
};
更新 1:
提案之一的相同结果:
我建议你使用testing-library/react which could be use smoothly with jest and provide async methods
你的测试会变成这样:
import React from "react";
import Hello from "./Hello";
import { render } from '@testing-library/react';
it("works", () => {
const { baseElement } = render(<Hello />);
expect(baseElement).toBeTruthy();
});
编辑:为了完整起见,在您的示例中,您试图测试组件中的更新是否发生在使用承诺的效果之后。
为了 waitFor 一些异步你可以使用方法 findBy (findBy 方法是 getBy 查询和 waitFor 的组合。)
import React from "react";
import Hello from "./Hello";
import { render, findByText } from "@testing-library/react";
import "@testing-library/jest-dom";
it("works", async () => {
const { baseElement } = render(<Hello />);
expect(await findByText(baseElement, "Hello! 4")).toBeVisible();
});
让我解释一下,import "@testing-library/jest-dom"
允许您使用方法 toBeVisible
因此,此测试正在渲染一个组件 Hello,然后它在 baseElement(即组件本身)内等待(默认值 1000 毫秒)寻找文本“Hello!4”,如果找到,它将return找到的元素,我们要测试它是否可见。
看起来这个示例工作正常
import React from "react";
import Hello from "./Hello";
import { render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
it("works", () => {
render(<Hello />);
return waitFor(() => screen.getByText("Hello! 4"));
// expect(baseElement.toBeTruthy();
});