[英]How to resolve act() in useEffect?
我在 react-testing-library 中遇到 act() 錯誤的小問題。 在 useEffect 中,我嘗試調用一個 function,它是一個 promise。Promise 返回一些數據並顯示它,但即使測試通過,仍然顯示行為錯誤。 成分:
export function getUser() {
return Promise.resolve({ name: "Json" });
}
const Foo = () => {
const [user, setUser] = useState(null);
useEffect(() => {
const loadUser = async () => {
const userData = await getUser();
setUser(userData);
};
loadUser();
}, []);
return (
<div>
<p>foo</p>
{user ? <p>User is: {user.name}</p> : <p>nothing</p>}
</div>
);
};
我的 Foo 組件也在 App Component 中,就像這樣:
import Foo from "./components/Foo";
function App() {
return (
<div>
some value
<Foo />
</div>
);
}
export default App;
測試:
test("should display userName", async () => {
render(<Foo />);
expect(screen.queryByText(/User is:/i)).toBeNull();
expect(await screen.findByText(/User is: JSON/i)).toBeInTheDocument();
});
你有什么想法來解決它嗎?
編輯:這是一條錯誤消息
console.error
Warning: An update to Foo 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 */
而waitFor
act
讓渲染解析。
import { render, waitFor } from '@testing-library/react-native';
import { useEffect, useState } from 'react';
import { Text } from 'react-native';
describe('useState', () => {
it('useState', () => {
function MyComponent() {
const [foo] = useState('foo');
return <Text testID="asdf">{foo}</Text>;
}
const { getByTestId } = render(<MyComponent></MyComponent>)
expect(getByTestId("asdf").props.children).toBe("foo");
});
it('useState called async', async () => {
function MyComponent() {
const [foo, setFoo] = useState('foo');
useEffect(() => {
(async () => {
setFoo(await Promise.resolve('bar'))
})()
}, []);
return <Text testID="asdf">{foo}</Text>;
}
const {getByTestId} = await waitFor(()=>render(<MyComponent></MyComponent>))
expect(getByTestId("asdf").props.children).toBe("bar");
});
});
除了上述針對更新不會立即發生的情況(即超時)的答案之外,您還可以使用await act(()=>Promise.resolve());
(請注意,由於輸入不當,這會生成警告,但需要await
才能工作。
這是一個renderHook
的例子
it("should return undefined", async () => {
const { result } = renderHook(() => {
const [loaded, loadedFonts] = useExpoFonts([]);
return useReplaceWithNativeFontCallback(loaded, loadedFonts);
}, {});
const replaceWithNativeFont0 = result.current;
expect(replaceWithNativeFont0({})).toBeUndefined();
await act(() => Promise.resolve());
const replaceWithNativeFont1 = result.current;
expect(replaceWithNativeFont1({})).toBeUndefined();
});
it("should render fonts", async () => {
function MyComponent() {
const [loaded, loadedFonts] = useExpoFonts([]);
const replaceWithNativeFont = useReplaceWithNativeFontCallback(
loaded,
loadedFonts
);
const style = replaceWithNativeFont({
fontFamily: "something",
fontWeight: "300",
});
return <View testID="blah" style={style} />;
}
const { unmount } = render(
<ThemeProvider>
<MyComponent />
</ThemeProvider>
);
await act(() => Promise.resolve());
expect(screen.getByTestId("blah").props.style).toStrictEqual({
fontFamily: "something",
fontWeight: "300",
});
unmount();
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.