act
是一個測試輔助函式,用於在進行斷言之前應用待處理的 React 更新。
await act(async actFn)
要準備一個元件進行斷言,請將渲染它並執行更新的程式碼包裝在 await act()
呼叫中。這使得您的測試執行方式更接近 React 在瀏覽器中的工作方式。
參考
await act(async actFn)
在撰寫 UI 測試時,諸如渲染、使用者事件或資料擷取等任務可以被視為與使用者介面互動的「單元」。React 提供了一個名為 act()
的輔助函式,可確保在您進行任何斷言之前,與這些「單元」相關的所有更新都已處理並套用至 DOM。
名稱 act
來自 安排-動作-斷言 (Arrange-Act-Assert) 模式。
it ('renders with button disabled', async () => {
await act(async () => {
root.render(<TestComponent />)
});
expect(container.querySelector('button')).toBeDisabled();
});
參數
async actFn
:一個非同步函式,包裝了正在測試的元件的渲染或互動。在actFn
內觸發的任何更新,都會被新增到內部的 act 佇列中,然後一起清空以處理並將任何變更套用至 DOM。由於它是異步的,React 也會執行任何跨越異步邊界的程式碼,並清空任何已排程的更新。
回傳值
act
不會回傳任何值。
用法
在測試元件時,您可以使用 act
來對其輸出進行斷言。
例如,假設我們有這個 Counter
元件,以下的使用範例將示範如何測試它。
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(prev => prev + 1);
}
useEffect(() => {
document.title = `You clicked ${this.state.count} times`;
}, [count]);
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
)
}
在測試中渲染元件
要測試元件的渲染輸出,請將渲染程式碼包在 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
元件。這確保元件在進行斷言之前已完成渲染並套用其效果。
使用 act
確保在我們進行斷言之前,所有更新都已套用。
在測試中觸發事件
要測試事件,請將事件觸發程式碼包在 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()
函式內觸發事件。這確保在進行斷言之前,所有來自事件的更新都已套用。
疑難排解
我收到一個錯誤訊息:「目前的測試環境未設定為支援 act(…)」
使用 act
需要在您的測試環境中設定 global.IS_REACT_ACT_ENVIRONMENT=true
。這是為了確保 act
僅在正確的環境中使用。
如果您沒有設定全域變數,您將看到如下錯誤:
主控台
警告:目前的測試環境未設定為支援 act(…)
要解決此問題,請將以下程式碼新增到您的 React 測試的全域設定檔中:
global.IS_REACT_ACT_ENVIRONMENT=true