简体   繁体   English

Mocking react-router-dom 使用 jest 的钩子不起作用

[英]Mocking react-router-dom hooks using jest is not working

I'm using Enzyme's shallow method to test a component which uses the useParams hook to get an ID from the URL params.我正在使用 Enzyme 的浅层方法来测试一个组件,该组件使用useParams挂钩从 URL 参数中获取 ID。

I'm trying to mock the useParams hook so that it does't call the actual method, but it doesn't work.我试图模拟useParams钩子,使其不调用实际方法,但它不起作用。 I'm still getting TypeError: Cannot read property 'match' of undefined , so it calls the actual useParams , and not my mock.我仍然收到TypeError: Cannot read property 'match' of undefined ,所以它调用实际的useParams ,而不是我的模拟。

My component:我的组件:

import React from 'react';
import { useParams } from 'react-router-dom';

export default () => {

  const { id } = useParams();

  return <div>{id}</div>;

};

Test:测试:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import Header from './header';
import { shallow } from 'enzyme';

Enzyme.configure({ adapter: new Adapter() });

describe('<Header />', () => {

  jest.mock('react-router-dom', () => ({
    useParams: jest.fn().mockReturnValue({ id: '123' }),
  }));

  it('renders', () => {
    const wrapper = shallow(<Header />);
    expect(wrapper).toBeTruthy();
  });

});

Thank you!谢谢!

I am not sure why, also couldn't find it in the docs of react-router library, but changing react-router-dom to react-router in both tests and implementation worked for me.我不知道为什么,在 react-router 库的文档中也找不到它,但是在测试和实现中将react-router-dom更改为react-router对我有用。

So it becomes something like this:所以它变成了这样:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import Header from './header';
import { shallow } from 'enzyme';

Enzyme.configure({ adapter: new Adapter() });

describe('<Header />', () => {

  jest.mock('react-router', () => ({
    useParams: jest.fn().mockReturnValue({ id: '123' }),
  }));

  it('renders', () => {
    const wrapper = shallow(<Header />);
    expect(wrapper).toBeTruthy();
  });

});

I tried this mock but it doesn't work to me.我试过这个模拟,但它对我不起作用。 Error: Cannot read property 'match' of undefined.错误:无法读取未定义的属性“匹配”。 It seems the component is not inside a router so it cannot mock the match with params.似乎该组件不在路由器内部,因此它无法使用参数模拟匹配。 It works to me:它对我有用:

import { MemoryRouter, Route } from 'react-router-dom';

const RenderWithRouter = ({ children }) => (
  <MemoryRouter initialEntries={['uri/Ineed']}>
    <Route path="route/Ineed/:paramId">{children}</Route>
  </MemoryRouter>
);
const tf = new TestFramework();
describe('<MyComponent />', () => {
  tf.init({ title: 'Some test' }, props =>
    shallow(
      <RenderWithRouter>
        <MyComponent {...props} />
      </RenderWithRouter>
    )
  );

  it('Some description', () => {
    const wrapper = tf.render().html();
    expect(wrapper).toContain('something');
  });
});

I've had a similar problem, I solved it like this:我遇到了类似的问题,我是这样解决的:

import { Route, Router } from "react-router-dom";
import { createMemoryHistory } from "history";

const renderWithRouter = (component) => {
  const history = createMemoryHistory({
    initialEntries: ["/part1/idValue1/part2/idValue2/part3"],
  });
  const Wrapper = ({ children }) => (
    <Router history={history}>
      <Route path="/part1/:id1/part2/:id2/part3">{children}</Route>
    </Router>
  );
  return {
    ...render(component, { wrapper: Wrapper }),
    history,
  };
};

describe("test", () => {
  it("test desc", async () => {
    const { getByText } = renderWithRouter(<MyComponent/>);
    expect(getByText("idValue1")).toBeTruthy();
  });
});

For me mocking react-router-dom fix the issue:对我来说 mocking react-router-dom 修复问题:

jest.mock('react-router-dom', () => ({
    useParams: jest.fn().mockReturnValue({ nifUuid: 'nif123' }),
    useHistory: jest.fn()
}));

This works for me to mock useParams and change values for each unit test within the same file:这对我来说可以模拟 useParams 并更改同一文件中每个单元测试的值:

import React from "react";
import { render } from "@testing-library/react";
import Router from "react-router-dom";
import Component from "./Component";

jest.mock("react-router-dom", () => ({
 ...jest.requireActual("react-router-dom"),
 useParams: jest.fn(),
}));

const createWrapper = () => {
 return render(<Cases />);
};

describe("Component Page", () => {
 describe("Rendering", () => {
   it("should render cases container", () => {
     jest.spyOn(Router, 'useParams').mockReturnValue({ id: '1234' })
     const wrapper = createWrapper();
     expect(wrapper).toMatchSnapshot();
   });

   it("should render details container", () => {
     jest.spyOn(Router, 'useParams').mockReturnValue({ id: '5678' })
     const wrapper = createWrapper();
     expect(wrapper).toMatchSnapshot();
   });
 });
});

Just declare useParams as jest.fn() outside describe() and then change its values in each unit test with jest.spyOn只需在 describe() 之外将useParams声明为jest.fn() ) ,然后在每个单元测试中使用jest.spyOn更改其值

I had the same issue.我遇到过同样的问题。 I mocked useParams like this:我像这样嘲笑 useParams :

jest.mock('react-router-dom', () => {
  return {
    useParams: () => ({
      id: '123'
    })
  }
})

I had the same issue.我遇到过同样的问题。 Calling the "cleanup" function from the "@testing-library/react" helps me:从“@testing-library/react”调用“清理”function 可以帮助我:

import { cleanup } from '@testing-library/react';

afterEach(() => {
    cleanup();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM