像“useLocation”这样的反应路由器钩子的存根不起作用

αƞj*_*jiβ 5 reactjs react-router enzyme react-hooks

我正在尝试为 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);
  });
});
Run Code Online (Sandbox Code Playgroud)

就连我也蠢蠢欲动useLocation我也会收到错误

TypeError: Cannot read property 'location' of undefined
at useLocation (node_modules\react-router\modules\hooks.js:28:10)
Run Code Online (Sandbox Code Playgroud)

我正在尝试测试ShowStatus组件是否根据查询参数使用正确的道具进行渲染。

任何建议/帮助表示赞赏。

更新: 我注意到即使我从react-router-dom产品代码和测试代码中导入。我看到 prod one 正在从 中获取react-router

sli*_*wp2 2

使用MemoryRouter组件包裹你的组件比stub更好useLocation组件包装您的组件比存根钩子

\n
\n

将 \xe2\x80\x9cURL\xe2\x80\x9d 的历史记录保留在内存中(不读取或写入地址栏)。在测试和非浏览器环境(如 React Native)中很有用。

\n
\n

我们可以通过initialEntries属性向您的被测组件提供“URL” 。

\n

index.tsx

\n
import React from \'react\';\nimport { useLocation } from \'react-router-dom\';\n\nexport function ShowStatus({ message, secret }) {\n  return <div>{message}</div>;\n}\n\nexport function MyComponent(props) {\n  const useQuery = () => new URLSearchParams(useLocation().search);\n  const status = useQuery().get(\'status\');\n\n  if (status === \'success\') {\n    return <ShowStatus message="OK" secret={props.secret} />;\n  } else {\n    return <ShowStatus message="NOT OK" secret={props.secret} />;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

index.test.tsx

\n
import { mount } from \'enzyme\';\nimport React from \'react\';\nimport { MemoryRouter } from \'react-router\';\nimport { MyComponent, ShowStatus } from \'./\';\n\ndescribe(\'MyComponent\', () => {\n  it(\'should send OK when success\', () => {\n    const props = { secret: \'SECRET_KEY\' };\n    const wrapper = mount(\n      <MemoryRouter initialEntries={[{ search: \'?status=success\' }]}>\n        <MyComponent {...props} />\n      </MemoryRouter>\n    );\n    expect(wrapper.find(ShowStatus).props().message).toEqual(\'OK\');\n    expect(wrapper.find(MyComponent).props().secret).toEqual(props.secret);\n  });\n\n  it(\'should send NOT OK when error\', () => {\n    const props = { secret: \'SECRET_KEY\' };\n    const wrapper = mount(\n      <MemoryRouter initialEntries={[{ search: \'?status=error\' }]}>\n        <MyComponent {...props} />\n      </MemoryRouter>\n    );\n\n    expect(wrapper.find(ShowStatus).props().message).toEqual(\'NOT OK\');\n    expect(wrapper.find(MyComponent).props().secret).toEqual(props.secret);\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
 PASS  examples/59829930/index.test.tsx (8.239 s)\n  MyComponent\n    \xe2\x9c\x93 should send OK when success (55 ms)\n    \xe2\x9c\x93 should send NOT OK when error (8 ms)\n\n-----------|---------|----------|---------|---------|-------------------\nFile       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n-----------|---------|----------|---------|---------|-------------------\nAll files  |     100 |      100 |     100 |     100 |                   \n index.tsx |     100 |      100 |     100 |     100 |                   \n-----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        9.003 s\n
Run Code Online (Sandbox Code Playgroud)\n

软件包版本:

\n
import React from \'react\';\nimport { useLocation } from \'react-router-dom\';\n\nexport function ShowStatus({ message, secret }) {\n  return <div>{message}</div>;\n}\n\nexport function MyComponent(props) {\n  const useQuery = () => new URLSearchParams(useLocation().search);\n  const status = useQuery().get(\'status\');\n\n  if (status === \'success\') {\n    return <ShowStatus message="OK" secret={props.secret} />;\n  } else {\n    return <ShowStatus message="NOT OK" secret={props.secret} />;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n