网站搜索

reactjs - 我如何测试被 withRouter 包裹的 React 组件的回调?


我正在使用 Jest 和 Enzyme 来测试一个用 TypeScript 编写的 React 项目。我有一个组件,它被包装在 React-Router 路由器中,看起来大致如下:

import { SomeButton } from './someButton';
import { RouteComponentProps, withRouter } from 'react-router';

const SomeButtonWithRouter = withRouter<{buttonCallback: () => void}>(SomeButton);

export class SomePage extends React.Component <RouteComponentProps<{}>, {}> {
  constructor(props: {}) {
    super(props);

    this.someCallback = this.someCallback.bind(this);
  }

  public render() {
    return (
      <div>
        <SomeButtonWithRouter buttonCallback={this.someCallback}/>
      </div>
    );
  }

  // This is the callback I want to  test:
  private someCallback() {
    console.log('This is a callback');
  }

现在我正在尝试编写一个测试,该测试调用 someCallback,然后进行一些断言。我已经将 SomePage 包装在 MemoryRouter 中,以便能够进行测试:

it('should do something', () => {
  const page = mount(<MemoryRouter><SomePage/></MemoryRouter>);
  const cb = page.find('SomeButton').prop('buttonCallback'); // <-- this is undefined
});

如评论中所述,不幸的是,当这样访问时,buttonCallback 属性是未定义的。不过,当我输出 page 时,它确实显示已定义:

<withRouter(SomeButton)
  onVerified={[Function bound ]}

以及下面的一些行:

<SomeButton
  history={ // ...
  // ...
  onVerified={[Function bound ]}

对于 Enzyme 的 find,SomeButton 和 withRouter(SomeButton) 都不能作为选择器使用。

我不确定为什么会这样;我确实能够通过这种方式访问另一个没有被 withRouter 包裹的子组件的回调。我也不确定我所做的一切是否是正确的做法,所以任何关于更好做法的指点都是欢迎的。

答案#1

咕…像往常一样,一夜的睡眠让我找出了问题——实际上问题并不在这里。如果对任何人有帮助,我会详细说明我犯的错误。

首先,最有用的信息是:const cb=page.find('SomeButton').prop('buttonCallback'); 和 const cb=page.find('withRouter(SomeButton)').prop('buttonCallback'); 都应该可以工作——尽管我会选择前者,因为这样你就不需要了解路由的使用。

其次,我认为它不起作用的原因是因为我试图使用 toJson(page.find('SomeButton').prop('buttonCallback'))(使用 enzyme-to-json)输出结果,而这会把该函数高兴地转换为 undefined。

最后,这也是最愚蠢的事情——我没有看到调用回调的效果,因为……我实际上并没有调用它。我只是将它赋值为 const buttonCallback=page.find...,但接着还必须写 buttonCallback()。哦,还有:我之后的断言里有一个拼写错误。

我知道,很蠢。当你六个月后遇到这个问题时,随便嘲笑我吧。