感谢@Estus Flask提供了非常有用的答案。我之前只使用了setTimeout功能,但是无法使测试正常工作。在测试中调用setTimeout
会导致嵌套调用,jest.useFakeTimers()
和jest.runAllTimers()
似乎没有任何作用,我一直卡在获取加载器上。由于寻找正确的测试方法花费了很长时间,我认为分享我如何测试它将会很有帮助。根据给定解决方案的实现:
import React, { ReactElement, Suspense } from 'react';
import { Outlet, Route, Routes } from 'react-router-dom';
import Loader from 'app/common/components/Loader';
const Navigation = React.lazy(() => {
return Promise.all([
import("./Navigation"),
new Promise(resolve => setTimeout(resolve, 300))
])
.then(([moduleExports]) => moduleExports);
});
const Home = React.lazy(() => {
return Promise.all([
import("./Home"),
new Promise(resolve => setTimeout(resolve, 300))
])
.then(([moduleExports]) => moduleExports);
});
interface PagesProps {
toggleTheme: () => void;
}
const Pages = (props: PagesProps): ReactElement => (
<Suspense fallback={<Loader />}>
<Routes>
<Route path="/" element={
<>
<Navigation toggleTheme={props.toggleTheme}/>
<Outlet />
</>
}>
<Route index element={<Home />} />
</Route>
</Routes>
</Suspense>
);
export default Pages;
我能够成功地使用以下内容进行测试。请注意,如果您不包括 jest.useFakeTimers()
和 jest.runAllTimers()
,则会看到不稳定的测试结果。我的测试用例中有一些多余的细节,因为我还在测试历史记录推送(在其他测试中),但希望这对任何人都有所帮助!
import { render, screen, cleanup, waitFor } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router-dom';
import Pages from './';
describe('Pages component', () => {
beforeEach(() => {
jest.useFakeTimers();
})
const history = createMemoryHistory();
it('displays loader when lazy', async () => {
render(
<Router location={history.location} navigator={history} navigationType={history.action}>
<Pages toggleTheme={function (): void { return null; } } />
</Router>,
);
const lazyElement = await screen.findByText(/please wait/i);
expect(lazyElement).toBeInTheDocument();
});
it('displays "Welcome!" on Home page lazily', async () => {
render(
<Router location={history.location} navigator={history} navigationType={history.action}>
<Pages toggleTheme={function (): void { return null; } } />
</Router>,
);
const fallbackLoader = await screen.findByText(/please wait/i);
expect(fallbackLoader).toBeInTheDocument();
jest.runAllTimers();
const lazyElement = await screen.findByText('Welcome!');
expect(lazyElement).toBeInTheDocument();
});
afterEach(cleanup);
});