使用开玩笑嘲笑react-router-dom挂钩不起作用

时间:2019-11-15 19:33:30

标签: reactjs react-router jestjs enzyme react-hooks

我正在使用酶的浅层方法来测试使用useParams挂钩从URL参数获取ID的组件。

我正在尝试模拟useParams钩子,以便它不调用实际方法,但是不起作用。我仍然得到TypeError: Cannot read property 'match' of undefined,因此它称为实际的useParams,而不是我的模拟。

我的组件

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

export default () => {

  const { id } = useParams();

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

};

测试:

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();
  });

});

谢谢!

6 个答案:

答案 0 :(得分:3)

我尝试了这个模拟,但是对我不起作用。错误:无法读取未定义的属性“匹配”。似乎该组件不在路由器内部,因此它无法使用参数模拟匹配。它对我有用:

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');
  });
});

答案 1 :(得分:1)

我不确定为什么,在react-router库的文档中也找不到它,但是在测试和实现中将react-router-dom更改为react-router都对我有用。

所以它变成了这样的东西:

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();
  });

});

答案 2 :(得分:0)

我遇到了类似的问题,我这样解决了它:

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();
  });
});

答案 3 :(得分:0)

对我来说,嘲笑 react-router-dom 解决了这个问题:

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

答案 4 :(得分:0)

这对我有用,可以模拟 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();
   });
 });
});

只需在 describe() 之外将 useParams 声明为 jest.fn(),然后在每个单元测试中使用 jest.spyOn

更改其值

答案 5 :(得分:-1)

我有同样的问题。 从“ @ testing-library / react”中调用“清理”功能对我有帮助:

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

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