reactjs - 像 'useLocation' 这样的 react 路由器钩子(Hook)的 stub 不起作用

标签 reactjs react-hooks react-router enzyme

我正在尝试为具有路由器 Hook 的 React 功能组件编写单元测试 useLocation()像下面。

//index.js
function MyComponent(props) {
  const useQuery = () => new URLSearchParams(useLocation().search);
   const status = useQuery().get('status');

  if (status === 'success') {
    return <ShowStatus message="OK" secret={props.secret} />;
  } else {
    return <ShowStatus message="NOT OK" secret={props.secret} />;
  }
}

//index.spec.js
describe('Test MyComponent', () => {
  it('should send OK when success', () => {
     sinon.stub(reactRouter, 'useLocation').returns({
        search: {
            status: 'success'
        }
     });
     const props = { secret: 'SECRET_KEY' };
     const wrapper = enzyme.shallow(<MyComponent.WrappedComponent {...props}/>);

     expect(wrapper.type()).to.have.length(MyComponent);
     expect(wrapper.props().message).to.equal('OK');
     expect(wrapper.props().secret).to.equal(props.secret);
  });

  it('should send NOT OK when error', () => {
     sinon.stub(reactRouter, 'useLocation').returns({
        search: {
            status: 'error'
        }
     });
     const props = { secret: 'SECRET_KEY' };
     const wrapper = enzyme.shallow(<MyComponent.WrappedComponent {...props}/>);

     expect(wrapper.type()).to.have.length(MyComponent);
     expect(wrapper.props().message).to.equal('NOT OK);
     expect(wrapper.props().secret).to.equal(props.secret);
  });
});
连我都 stub useLocation我收到错误
TypeError: Cannot read property 'location' of undefined
at useLocation (node_modules\react-router\modules\hooks.js:28:10)
我正在尝试测试 ShowStatus组件根据查询参数使用正确的 Prop 呈现。
任何建议/帮助表示赞赏。
更新:
我注意到即使我是从 react-router-dom 进口的在生产和测试代码中。我正在看到一个来自 react-router 的产品.

最佳答案

使用 MemoryRouter组件包装你的组件比 stub 更好 useLocation钩。

keeps the history of your “URL” in memory (does not read or write to the address bar). Useful in tests and non-browser environments like React Native.


我们可以通过 initialEntries 为您测试的组件提供“URL” Prop 。index.tsx :
import React from 'react';
import { useLocation } from 'react-router-dom';

export function ShowStatus({ message, secret }) {
  return <div>{message}</div>;
}

export function MyComponent(props) {
  const useQuery = () => new URLSearchParams(useLocation().search);
  const status = useQuery().get('status');

  if (status === 'success') {
    return <ShowStatus message="OK" secret={props.secret} />;
  } else {
    return <ShowStatus message="NOT OK" secret={props.secret} />;
  }
}
index.test.tsx :
import { mount } from 'enzyme';
import React from 'react';
import { MemoryRouter } from 'react-router';
import { MyComponent, ShowStatus } from './';

describe('MyComponent', () => {
  it('should send OK when success', () => {
    const props = { secret: 'SECRET_KEY' };
    const wrapper = mount(
      <MemoryRouter initialEntries={[{ search: '?status=success' }]}>
        <MyComponent {...props} />
      </MemoryRouter>
    );
    expect(wrapper.find(ShowStatus).props().message).toEqual('OK');
    expect(wrapper.find(MyComponent).props().secret).toEqual(props.secret);
  });

  it('should send NOT OK when error', () => {
    const props = { secret: 'SECRET_KEY' };
    const wrapper = mount(
      <MemoryRouter initialEntries={[{ search: '?status=error' }]}>
        <MyComponent {...props} />
      </MemoryRouter>
    );

    expect(wrapper.find(ShowStatus).props().message).toEqual('NOT OK');
    expect(wrapper.find(MyComponent).props().secret).toEqual(props.secret);
  });
});
测试结果:
 PASS  examples/59829930/index.test.tsx (8.239 s)
  MyComponent
    ✓ should send OK when success (55 ms)
    ✓ should send NOT OK when error (8 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.tsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        9.003 s
包版本:
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"jest": "^26.6.3",
"react": "^16.14.0",
"react-router-dom": "^5.2.0",

关于reactjs - 像 'useLocation' 这样的 react 路由器钩子(Hook)的 stub 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59829930/

相关文章:

node.js - 使用 ReactDOM.hydrate 进行服务器端渲染

javascript - 从 react 中映射的选择输入中获取选定的值

javascript - 如何将焦点设置到下一个输入上的输入键按下 react js与refs

javascript - 使用 redux 和 react 的异步服务器端渲染

html - React Router 只有一个链接可以工作 Github Pages

javascript - 在映射的子项上 react mouseEnter 事件不起作用

javascript - 如何在我的类组件中使用 useFormikContext Hook ?

reactjs - react Hook : Send data from child to parent component

javascript - 不要在特定路线上渲染组件

reactjs - 如何使用refreshControl在React Native ScrollView中刷新?