我是单元测试领域的新手,我才刚刚开始为我的React Native(Expo)应用编写测试。经过研究,我终于开始使用Jest和React Native Testing Library(https://github.com/callstack/react-native-testing-library)。
请考虑以下使用AppLoading组件(https://docs.expo.io/versions/latest/sdk/app-loading/)的情况。
const App: React.FC = () => {
const [resourcesHasLoaded, setResourcesHasLoaded] = useState<boolean>(false);
const cacheResources = useCallback(async (): Promise<any> => {
const images = [require('./assets/icon.png')];
const cacheImages = images.map((image) => {
return Asset.fromModule(image).downloadAsync();
});
return Promise.all([cacheImages]);
}, []);
if (resourcesHasLoaded) {
return <Text>Hello world</Text>;
}
return (
<AppLoading
startAsync={cacheResources}
onError={console.warn}
onFinish={() => setResourcesHasLoaded(true)}
/>
);
};
运行测试时,看起来像这样:
describe('App.tsx', () => {
it('should be able to render', async () => {
render(<App />);
});
});
我最终遇到以下错误(尽管通过测试):
Warning: An update to App 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 */
因此,我通过以下方式用render
将act
包裹起来:
act(() => {
render(<App />);
});
...导致了同样的错误。
但是,如果我通过以下方式将onFinish
回调包装在组件中,则测试将通过而不会发出警告。
onFinish={() => act(() => setResourcesHasLoaded(true))}
但是我真的想用测试专用功能污染我的React组件吗?我没有看到这样的例子,所以我只能认为这是一种不好的做法。
这里有什么建议吗?
更新
我得到@Estus Flask在我的waitFor
之后的建议中使用render
。这样就可以了...测试现在通过了。
https://callstack.github.io/react-native-testing-library/docs/api/#waitfor
describe('App.tsx', () => {
it('should be able to render', async () => {
const { findByText } = render(<MyApp />);
await waitFor(() => findByText('Hello world'));
});
});