你如何使用浅层测试酶 Reactjs 模拟 useLocation() 路径名?

pur*_*037 22 reactjs jestjs react-router enzyme

我有如下标题组件:

import { useLocation } from "react-router-dom";

const Header = () => {
   let route = useLocation().pathname; 
   return route === "/user" ? <ComponentA /> : <ComponentB />;
}
Run Code Online (Sandbox Code Playgroud)

您将如何模拟这个 useLocation() 以获取用户路径?

我不能简单地在我的测试文件中调用 Header 组件,因为我收到错误:

类型错误:无法在 useLocation 读取未定义的属性“位置”

describe("<Header/>", () => {
    it("call the header component", () => {
        const wrapper = shallow(<Header />);
        expect(wrapper.find(ComponentA)).toHaveLength(1);
    });
});
Run Code Online (Sandbox Code Playgroud)

我试过看起来类似于链接如何使用新的反应路由器钩子测试组件?但它没有用。

我试过如下:

const wrapper = shallow(
      <Provider store={store}>
        <MemoryRouter initialEntries={['/abc']}>
          <Switch>
            <AppRouter />
          </Switch>
        </MemoryRouter>
      </Provider>,
    );
    jestExpect(wrapper.find(AppRouter)
      .dive()
      .find(Route)
      .filter({path: '/abc'})
      .renderProp('render', { history: mockedHistory})
      .find(ContainerABC)
    ).toHaveLength(1);
Run Code Online (Sandbox Code Playgroud)

来自使用浅渲染测试反应路由器的链接但它没有用。

请告诉我。

提前致谢。

jac*_*son 41

我发现我可以使用以下模式模拟像 useLocation 这样的 React Router 钩子:

import React from "react"
import ExampleComponent from "./ExampleComponent"
import { shallow } from "enzyme"

jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useLocation: () => ({
    pathname: "localhost:3000/example/path"
  })
}));

describe("<ExampleComponent />", () => {
  it("should render ExampleComponent", () => {
    shallow(<ExampleComponent/>);
  });
});
Run Code Online (Sandbox Code Playgroud)

如果您在 ExampleComponent 中调用了 useLocation,则上述模式应该允许您在 Enzyme / Jest 测试中浅渲染组件而不会出错。希望有帮助!

  • 我可以确认这有效。您还可以将其放在“__mocks__/react-router-dom.js”中,并将其添加到“package.json”中的“jest.setupFiles”中,以便在多个测试之间共享。 (4认同)

小智 7

我最近也在纠结这个。。。

我发现这很好用:

import React from "react"
import ExampleComponent from "./ExampleComponent"
import { shallow } from "enzyme"

const mockUseLocationValue = {
    pathname: "/testroute",
    search: '',
    hash: '',
    state: null
}
jest.mock('react-router', () => ({
    ...jest.requireActual("react-router") as {},
    useLocation: jest.fn().mockImplementation(() => {
        return mockUseLocationValue;
    })
}));

describe("<ExampleComponent />", () => {
  it("should render ExampleComponent", () => {
    mockUseLocationValue.pathname = "test specific path";
    shallow(<ExampleComponent/>);
    ...
    expect(...
  });
});
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我能够模拟 useLocation 并根据需要在特定测试中为路径名提供值。

HTH

  • 完美,这应该是例外的答案。我还建议在每个测试用例之前重置模拟位置。 (4认同)
  • 这会导致“类型错误:无法读取未定义的属性‘路径名’” (2认同)

Alf*_*Alf 2

我知道这不是 \xe2\x80\x99t 对您问题的直接答案,但如果您想要测试浏览器位置或历史记录,您可以使用并在末尾mount添加一个额外的\xe2\x80\x9ccapture Route\xe2\x80\x9d 历史和位置对象。

\n\n
test(`Foobar`, () => {\n  let testHistory\n  let testLocation\n\n  const wrapper = mount(\n    <MemoryRouter initialEntries={[`/`]}>\n      <MyRoutes />\n      <Route\n        path={`*`}\n        render={routeProps => {\n          testHistory = routeProps.history\n          testLocation = routeProps.location\n          return null\n        }}/>\n    </MemoryRouter>\n  )\n\n  // Manipulate wrapper\n\n  expect(testHistory)...\n  expect(testLocation)...\n)}\n
Run Code Online (Sandbox Code Playgroud)\n