ale*_*17k 1 javascript reactjs jestjs enzyme
给定一个包含多个延迟加载路由的简单应用程序,
import React, { lazy, Suspense } from "react";
import { Route } from "react-router-dom";
import "./styles.css";
const Component = lazy(() => import("./Component"));
const PageNotFound = lazy(() => import("./PageNotFound"));
export default function App() {
return (
<div className="App">
<Route
path="/component"
exact
render={() => (
<Suspense fallback={<div>Loading..</div>}>
<Component />
</Suspense>
)}
/>
<Route
path="*"
render={() => (
<Suspense fallback={<div>Loading..</div>}>
<PageNotFound />
</Suspense>
)}
/>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
如何进行测试来检查这些组件是否正在该特定路线上呈现?
这是我尝试过的 App.test:
import { configure, shallow, mount } from "enzyme";
import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
import React from "react";
import { MemoryRouter } from "react-router-dom";
import App from "./App";
import Component from "./Component";
import PageNotFound from "./PageNotFound";
configure({ adapter: new Adapter() });
describe("App", () => {
it("renders without crashing", () => {
shallow(<App />);
});
it("renders lazy loaded PageNotFound route", () => {
// Act
const wrapper = mount(
<MemoryRouter initialEntries={["/random"]}>
<App />
</MemoryRouter>
);
// Assert
// expect(wrapper.containsMatchingElement(<PageNotFound />)).toEqual(true);
// expect(wrapper.find(PageNotFound)).toHaveLength(1);
expect(wrapper.exists(PageNotFound)).toEqual(true);
});
});
Run Code Online (Sandbox Code Playgroud)
由于悬念,所有 3 个断言似乎都不起作用;可以在此处的codesandbox 找到工作片段- 确保进入“测试”选项卡以查看失败的测试。
非常感谢任何建议,提前谢谢您!
这是一个有趣的问题,很难有最好的方法来模拟,因为它lazy(() => import('path/to/file'))接受一个函数作为参数,所以我们无法检测匿名函数的值。
但我想我有一个适合您的解决方案,但最好不要测试所有情况,而是测试特定情况才有效。你会嘲笑如下:
jest.mock('react', () => {
const React = jest.requireActual('react');
// Always render children as our lazy mock component
const Suspense = ({ children }) => {
return children;
};
const lazy = () => {
// `require` component directly as we want to see
// Why? Above reason
return require('./PageNotFound').default;
}
return {
...React,
lazy,
Suspense
};
});
Run Code Online (Sandbox Code Playgroud)
lazy更新了mock函数的新方式我认为我有一个更好的主意来调用lazy参数然后作为组件返回,如下所示:
jest.mock('react', () => {
const React = jest.requireActual('react');
const Suspense = ({ children }) => {
return children;
};
const lazy = jest.fn().mockImplementation((fn) => {
const Component = (props) => {
const [C, setC] = React.useState();
React.useEffect(() => {
fn().then(v => {
setC(v)
});
}, []);
return C ? <C.default {...props} /> : null;
}
return Component;
})
return {
...React,
lazy,
Suspense
};
});
Run Code Online (Sandbox Code Playgroud)
然后,您必须等待模拟中返回的组件更新lazy,因此我们等待组件重新绘制,如下所示:
// keep warning `act` removed
import { act } from 'react-dom/test-utils';
// A helper to update wrapper
const waitForComponentToPaint = async (wrapper) => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve));
wrapper.update();
});
};
it("renders PageNotFound", async () => {
const wrapper = mount(
<MemoryRouter initialEntries={["/random"]}>
<App />
</MemoryRouter>
);
await waitForComponentToPaint(wrapper);
expect(wrapper.exists(PageNotFound)).toEqual(true);
});
it("renders Component", async () => {
const wrapper = mount(
<MemoryRouter initialEntries={["/component"]}>
<App />
</MemoryRouter>
);
await waitForComponentToPaint(wrapper);
expect(wrapper.exists(Component)).toEqual(true);
});
Run Code Online (Sandbox Code Playgroud)
我创建了一个repl.it链接供您检查其工作原理: https: //repl.it/@tmhao2005/js-cra
您可以运行测试:yarn test -- lazy。并浏览 下的代码src/Lazy。