reactjs - 如何使用 RouteComponentProps 测试 React 组件?

标签 reactjs typescript testing react-router jestjs

我有一个组件,它具有扩展 RouteComponentProps 的 Prop ,如下所示:

export interface RouteComponentProps<P> {
  match: match<P>;
  location: H.Location;
  history: H.History;
  staticContext?: any;
}

现在,当我在应用程序中使用我的组件时,我将这些 Prop 传递给它:

<MyComponent
    match={this.props.match}
    location={this.props.location}
    history={this.props.history}
/>

Prop 已经可用,因为它在 React 路由器中运行。

现在,如何在没有可用的matchlocationhistory 的情况下测试这个组件?

我需要模拟它们还是应该以某种辅助函数自动加载它们?

最佳答案

要回答您的最后一个问题,推荐的方法是使用 <MemoryRouter>< *your component here* ></MemoryRouter>在你的测试中。 Typescript 没有意识到该组件会将所需的 Prop 传递给您的组件,因此我认为它不是是一种类型安全的方法。

这适用于 React Router v4,不适用于以前的版本。

用于测试用 HOC 包装的组件的类型安全方法 withRouter您可以从 react-router 构建位置、历史记录和匹配项和 history包。

此示例使用 enzyme 和快照测试,但可以很容易地成为任何其他测试。

这避免了我需要使用 <MemoryRouter>作为 typescript 无论如何都不喜欢的包装器。

// Other imports here
import { createMemoryHistory, createLocation } from 'history';
import { match } from 'react-router';

const history = createMemoryHistory();
const path = `/route/:id`;

const match: match<{ id: string }> = {
    isExact: false,
    path,
    url: path.replace(':id', '1'),
    params: { id: "1" }
};

const location = createLocation(match.url);

test('shallow render', () => {
    const wrapper = shallow(
        <MyComponent history={history}
                     location={location}
                     match={match} />
    );

    expect(wrapper).toMatchSnapshot();
});

注意不要使用它来测试实现细节,它可能很诱人,但如果您想重构,它会给您带来很多痛苦。

为此制作一个助手可能是使其可重用的最佳方式。

import { createLocation, createMemoryHistory } from 'history';
import { match as routerMatch } from 'react-router';

type MatchParameter<Params> = { [K in keyof Params]?: string };

export const routerTestProps = <Params extends MatchParameter<Params> = {}>
    (path: string, params: Params, extendMatch: Partial<routerMatch<any>> = {}) => {
        const match: routerMatch<Params> = Object.assign({}, {
            isExact: false,
            path,
            url: generateUrl(path, params),
            params
        }, extendMatch);
        const history = createMemoryHistory();
        const location = createLocation(match.url);

        return { history, location, match };
    };


const generateUrl = <Params extends MatchParameter<Params>>
    (path: string, params: Params): string => {
        let tempPath = path;

        for (const param in params) {
            if (params.hasOwnProperty(param)) {
                const value = params[param];
                tempPath = tempPath.replace(
                    `:${param}`, value as NonNullable<typeof value>
                );
            }
        }

        return tempPath;
    };

现在我们可以使用 routerTestProps在我们的测试中发挥作用

const { history, location, match } = routerTestProps('/route/:id', { id: '1' });

关于reactjs - 如何使用 RouteComponentProps 测试 React 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46927392/

相关文章:

reactjs - 记住 React 中的所有内容是一种不好的做法吗?

reactjs - 通过扩展排版在 React 中使用 Material UI 进行 i18n 本地化?

javascript - 如何删除现有的http服务器?

reactjs - 如何对 Ant Design 的 Form getFieldDecorator() 进行 stub ?

javascript - postman 测试脚本

Angular4 componentInstance 和 debugElement.componentInstance 的区别

测试 RSS 提要

typescript - 如何在列表中键入具有属性的对象

javascript - 在 Javascript Webpack 项目中过渡到 Typescript(如何导出模块)

angular - 解析本地主机 :4200 while trying to serve angular application 时出错