act 是一个测试助手,用于在进行断言之前应用待处理的 React 更新。
await act(async actFn)为了为断言准备一个组件,将渲染它和执行更新的代码封装在一个 await act() 调用中。这使你的测试运行方式更接近 React 在浏览器中的工作方式。
🌐 To prepare a component for assertions, wrap the code rendering it and performing updates inside an await act() call. This makes your test run closer to how React works in the browser.
参考
🌐 Reference
await act(async actFn)
在编写 UI 测试时,像渲染、用户事件或数据获取这样的任务可以被视为与用户界面交互的“单元”。React 提供了一个名为 act() 的辅助工具,它可以确保在你进行任何断言之前,所有与这些“单元”相关的更新都已被处理并应用到 DOM。
🌐 When writing UI tests, tasks like rendering, user events, or data fetching can be considered as “units” of interaction with a user interface. React provides a helper called act() that makes sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions.
act 这个名字来源于 Arrange-Act-Assert 模式。
🌐 The name act comes from the Arrange-Act-Assert pattern.
it ('renders with button disabled', async () => {
await act(async () => {
root.render(<TestComponent />)
});
expect(container.querySelector('button')).toBeDisabled();
});参数
🌐 Parameters
async actFn:一个异步函数,用于封装正在测试的组件的渲染或交互。在actFn中触发的任何更新都会被添加到内部 act 队列中,然后一起刷新以处理并应用对 DOM 的任何更改。由于它是异步的,React 还会运行穿越异步边界的任何代码,并刷新任何已计划的更新。
返回
🌐 Returns
act 不返回任何值。
用法
🌐 Usage
在测试一个组件时,你可以使用 act 对其输出进行断言。
🌐 When testing a component, you can use act to make assertions about its output.
例如,假设我们有这个 Counter 组件,下面的使用示例展示了如何测试它:
🌐 For example, let’s say we have this Counter component, the usage examples below show how to test it:
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prev => prev + 1);
}
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>
Click me
</button>
</div>
)
}在测试中渲染组件
🌐 Rendering components in tests
要测试组件的渲染输出,请将渲染封装在 act() 内:
🌐 To test the render output of a component, wrap the render inside act():
import {act} from 'react';
import ReactDOMClient from 'react-dom/client';
import Counter from './Counter';
it('can render and update a counter', async () => {
container = document.createElement('div');
document.body.appendChild(container);
// ✅ Render the component inside act().
await act(() => {
ReactDOMClient.createRoot(container).render(<Counter />);
});
const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 0 times');
expect(document.title).toBe('You clicked 0 times');
});在这里,我们创建一个容器,将其附加到文档中,并在 act() 内渲染 Counter 组件。这确保组件在进行断言之前已被渲染并且其效果已被应用。
🌐 Here, we create a container, append it to the document, and render the Counter component inside act(). This ensures that the component is rendered and its effects are applied before making assertions.
使用 act 可以确保在我们进行断言之前已应用所有更新。
🌐 Using act ensures that all updates have been applied before we make assertions.
在测试中分派事件
🌐 Dispatching events in tests
要测试事件,将事件分发封装在 act() 内:
🌐 To test events, wrap the event dispatch inside act():
import {act} from 'react';
import ReactDOMClient from 'react-dom/client';
import Counter from './Counter';
it.only('can render and update a counter', async () => {
const container = document.createElement('div');
document.body.appendChild(container);
await act( async () => {
ReactDOMClient.createRoot(container).render(<Counter />);
});
// ✅ Dispatch the event inside act().
await act(async () => {
button.dispatchEvent(new MouseEvent('click', { bubbles: true }));
});
const button = container.querySelector('button');
const label = container.querySelector('p');
expect(label.textContent).toBe('You clicked 1 times');
expect(document.title).toBe('You clicked 1 times');
});在这里,我们使用 act 渲染组件,然后在另一个 act() 内部分发事件。这确保了在进行断言之前,事件的所有更新都已应用。
🌐 Here, we render the component with act, and then dispatch the event inside another act(). This ensures that all updates from the event are applied before making assertions.
故障排除
🌐 Troubleshooting
我收到一个错误:“当前测试环境未配置为支持 act(…)”
🌐 I’m getting an error: “The current testing environment is not configured to support act(…)”
使用 act 需要在你的测试环境中设置 global.IS_REACT_ACT_ENVIRONMENT=true。这是为了确保 act 仅在正确的环境中使用。
🌐 Using act requires setting global.IS_REACT_ACT_ENVIRONMENT=true in your test environment. This is to ensure that act is only used in the correct environment.
如果你未设置全局变量,你将看到如下错误:
🌐 If you don’t set the global, you will see an error like this:
要修复,请将其添加到 React 测试的全局设置文件中:
🌐 To fix, add this to your global setup file for React tests:
global.IS_REACT_ACT_ENVIRONMENT=true