javascript - React 测试库 - 未包含在 act() 错误中
问题描述
我在使用 react-testing-library 测试切换组件时遇到问题。
单击图标(包装在按钮组件中)时,我希望文本从“已验证”变为“未验证”。此外,在有状态更新的地方调用一个函数。
但是,单击事件似乎不起作用,并且出现以下错误:
> jest "MyFile.spec.tsx"
FAIL src/my/path/__tests__/MyFile.spec.tsx
component MyFile
✓ renders when opened (94 ms)
✓ renders with items (33 ms)
✕ toggles verification status on click of icon button (100 ms)
console.error
Warning: An update to MyFile inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at MyFile (/path/to/myfile.tsx:44:3)
at ThemeProvider (/users/node_modules/@material-ui/styles/ThemeProvider/ThemeProvider.js:48:24)
123 | );
124 | } finally {
> 125 | setIsLoading(false);
| ^
126 | }
127 | };
128 |
at printWarning (node_modules/react-dom/cjs/react-dom.development.js:67:30)
at error (node_modules/react-dom/cjs/react-dom.development.js:43:5)
at warnIfNotCurrentlyActingUpdatesInDEV (node_modules/react-dom/cjs/react-dom.development.js:24064:9)
at dispatchAction (node_modules/react-dom/cjs/react-dom.development.js:16135:9)
at handleConfirm (src/modules/myfile.tsx:125:7)
在我的代码中,我有一个这样的函数:
const handleSubmit = async() => {
if(isLoading) {
return;
}
try {
setIsLoading(true);
await myFunctionCalls();
} catch (error){
console.log(error)
} finally {
setIsLoading(false)
}
};
我的测试看起来与此类似:
test('toggles verification status on click of icon button', async () => {
renderWithTheme(
<MyComponent/>,
);
const updateVerificationMock = jest.fn();
const callFunctionWithSerializedPayloadMock =
callFunctionWithSerializedPayload as jest.Mock;
callFunctionWithSerializedPayloadMock.mockImplementation(
() => updateVerificationMock,
);
const button = screen.getByRole('button', {name: 'Remove approval'});
fireEvent.click(button);
await act(async () => {
expect(myFunctionCalls).toHaveBeenCalledTimes(1);
});
expect(await screen.findByText('unverified')).toBeInTheDocument();
});
当函数调用被调用一次时,第一个期望通过,但是我从上面遇到了 act() 错误,并且还有一个失败,因为文本似乎没有从verified
to切换unverified
。
我知道通常行为错误是异步/等待调用发生的问题,但我认为 findByText 应该等待,而且似乎还有另一个我没有在这里遇到的问题。有关如何调试/改进此测试的任何帮助?
解决方案
单击Remove Approval
按钮时,此处会调用 3 个异步函数。
首先,您将加载状态设置为true,因此它将加载然后调用异步函数(myFunctionCalls),最后,加载器将在加载状态设置为false后消失。
为了解决它,我们必须先等待加载出现,然后调用 myFunctionCalls,然后再等待加载消失。
test("toggles verification status on click of icon button", async () => {
renderWithTheme(<MyComponent />);
const updateVerificationMock = jest.fn();
const callFunctionWithSerializedPayloadMock =
callFunctionWithSerializedPayload as jest.Mock;
callFunctionWithSerializedPayloadMock.mockImplementation(
() => updateVerificationMock
);
const button = screen.getByRole("button", { name: "Remove approval" });
fireEvent.click(button);
expect(await screen.findByText(/loading/i)).toBeInTheDocument();
await waitFor(() => {
expect(myFunctionCalls).toHaveBeenCalledTimes(1);
});
await waitForTheElementToBeRemoved(() => {
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
});
expect(await screen.findByText("unverified")).toBeInTheDocument();
});
如果您没有加载文本,则可以使用act(() => jest.advanceTimersByTime(500));
将时间延长至 500 毫秒。当时间达到 500 毫秒时,异步功能将被解决。
beforeEach(() => {
jest.useFakeTimers();
})
afterEach(() => {
jest.runAllPendingTimers();
jest.useRealTimers()
})
test("toggles verification status on click of icon button", async () => {
renderWithTheme(<MyComponent />);
const updateVerificationMock = jest.fn();
const callFunctionWithSerializedPayloadMock =
callFunctionWithSerializedPayload as jest.Mock;
callFunctionWithSerializedPayloadMock.mockImplementation(
() => updateVerificationMock
);
const button = screen.getByRole("button", { name: "Remove approval" });
fireEvent.click(button);
act(() => jest.advanceTimersByTime(500));
await waitFor(() => {
expect(myFunctionCalls).toHaveBeenCalledTimes(1);
});
act(() => jest.advanceTimersByTime(500));
expect(await screen.findByText("unverified")).toBeInTheDocument();
});
推荐阅读
- azure-resource-group - 区域对于资源组是否重要?
- jupyter-notebook - 如何在 Jupyter Notebook 小部件中使用 FabricJS
- python - Selenium select_by_value 然后打印选项文本
- kotlin - 为什么每个线程多次初始化惰性变量
- windows - 如何在powershell中使用short_command_name -args而不是python program_name -args?
- android - 即使预览看起来不错,Scrollview 也没有在模拟器或手机中显示任何内容 已解决
- python - AttributeError:模块“django.db.models”没有属性“模型”
- eclipse - Mac OX 上用于 Eclipse 的 TFS 插件作为视图或透视图不可见
- microsoft-teams - Teams 选项卡中的 OneNote 链接在移动设备中不起作用
- vba - 如何在多个工作表上运行 3 个循环以进行条件格式设置