我用Jest和React测试库写了几个测试。它们都模拟fetch,并使用userEvent.click调用来触发提交按钮,从而发出fetch请求。状态在组件中得到更新,我做出Assert。我使用useEffect钩子来填充数据数组,但它只在初始加载时运行,因为我向它传递了一个空的依赖数组。目前我所有的测试都通过了。如果我把它们一起运行,我会得到一个错误的act()错误,它源于useEffect:
Warning: It looks like you're using the wrong act() around your test interactions.
Be sure to use the matching version of act() corresponding to your renderer:
// for react-dom:
import {act} from 'react-dom/test-utils';
// ...
act(() => ...);
// for react-test-renderer:
import TestRenderer from react-test-renderer';
const {act} = TestRenderer;
// ...
act(() => ...);
但是,当我单独运行其中一个时,我不会收到警告。我可以自己运行其中任何一个,而不会得到任何警告。只有在同时运行两个或更多测试时,我才会收到警告。
我的测试是:
describe("CartDetail", () => {
test("Order is submitted when user clicks Place Order button.", async () => {
global.fetch = jest.fn().mockImplementationOnce(() =>
Promise.resolve({
status: 200,
})
);
renderComponent();
await act(async () => {
userEvent.click(await screen.findByRole("button", { name: "Place Order" }));
});
expect(screen.queryByText("Your meal order was successfully processed.")).toBeInTheDocument();
});
test("Error message is displayed to user when order fails with a 400.", async () => {
global.fetch = jest.fn().mockImplementationOnce(() =>
Promise.resolve({
status: 400,
})
);
renderComponent();
await act(async () => {
userEvent.click(await screen.findByRole("button", { name: "Place Order" }));
});
expect(screen.queryByText("Please confirm that you are ordering at least one of each meal you have in your cart.")).toBeInTheDocument();
userEvent.click(screen.getByLabelText("Close alert"));
});
test("Error message is displayed to user when API fails.", async () => {
global.fetch = jest.fn().mockRejectedValueOnce(() =>
Promise.reject({
status: 500,
})
);
renderComponent();
await act(async () => {
userEvent.click(await screen.findByRole("button", { name: "Place Order" }));
});
expect(screen.queryByText("Your order failed.")).toBeInTheDocument();
userEvent.click(screen.getByLabelText("Close alert"));
});
});
我读到过你不必在act()中 Package userEvent,因为它已经在幕后了。然而,如果我没有将其封装在act中,我的测试就会失败并抛出:
Warning: An update to CartDetail 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 */
即使我注解掉了Assert,我的测试通过了(当然),但我仍然得到错误的act()警告。问题直接来自:
await act(async () => {
userEvent.click(await screen.findByRole("button", { name: "Place Order" }));
});
我不明白这个问题是如何从useEffect中产生的,当它在初始加载时执行并且不再运行时,包括通过www.example.com()单击按钮时userEvent.click。我已经搜索了互联网,没有什么比这更接近我了。This GitHub thread提到这是一个已知的问题,但它现在有点旧,所以我不知道它是否仍然有效。
4条答案
按热度按时间bttbmeg01#
您可能只需要等待
click
调用。在
14
版本中,像click
和type
这样的方法返回一个Promise
。这在13
版本中是不同的。y0u0uwnf2#
我终于找到了一个变通办法。这篇GitHub文章提到了在
act()
中 PackageuserEvent()
调用,我已经做过了。解决Warning: It looks like you're using the wrong act() around your test interactions.
控制台错误的方法是在userEvent()
调用之后和Assert之前添加以下代码:我更新的测试现在看起来像这样:
错误行为()警告现在已经消失。
ecfdbz9o3#
我的问题与此类似,因为我从
act(...)
块中获得了“useact(...)
”错误,但修复方法略有不同。根据这个https://github.com/testing-library/user-event/issues/255#issuecomment-624847626,
如果您使用act Package userEvent调用,它应该可以工作。react-testing-library中的fireEvent会自动执行此操作,但dom-testing-library中的fireEvent不会(因为act是react特性)。user-event从dom-testing-library调用fireEvent,因为这个库不是react特定的。
因此,我替换了
userEvent.click
并返回到fireEvent.click
,加上您使用macrotask等待微任务队列为空的修复,整个事情终于工作了。我的测试的其余部分使用
await ...find*(..)
而不是get
或query
,并且总是重新查找DOM元素而不是将其放入变量中,并且每个事件都通过helper函数 Package 在act
中。真是一团糟。感觉就像
@testing-library/react
在计算React重新渲染之类的东西,而不是等待React稳定下来。我有一个工作测试失败,只是因为在onClick处理程序中添加了一个愚蠢的await Promise.resolve();
,而这个处理程序已经是异步的。WTF.t8e9dugd4#
我在不同类型的测试中遇到了同样的问题。其中一些通过使用
await
和waitFor
进行Assert来修复使用
await waitFor(()=> expect(...))
对于剩余的测试,将react测试库更新到版本14解决了这个问题