如何使用RouteComponentProps测试React组件? [英] How to test a React component with RouteComponentProps?

查看:804
本文介绍了如何使用RouteComponentProps测试React组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a component that has props which extend RouteComponentProps that looks like this:

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

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

Now, when I use my component in the app, I pass these props to it:

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

道具已经可用,因为它在React Router中运行.

The props are available already because it's running inside react router.

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

Now, how do I test this component without match, location, history available?

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

Do I need to mock them or is it supposed to somehow automatically load them with some helper function?

推荐答案

要回答您的最后一个问题,建议的方法是在测试中使用<MemoryRouter>< *your component here* ></MemoryRouter>. Typescript不会接受此组件会将所需的属性传递给您的组件,因此,我认为是一种类型安全的方法.

To answer your last question, the recommended approach is to use <MemoryRouter>< *your component here* ></MemoryRouter> in your tests. Typescript does not pick up that this component will pass the required props to your component, as such I assume it not to be a type safe approach.

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

对于类型安全的方法来测试HOC withRouter包装的组件,可以从react-routerhistory包中构建位置,历史记录和匹配项.

For a typesafe method to test components that are wrapped with the HOC withRouter you can build the location, history and match from the react-router and history packages.

此示例使用了酶和快照测试,但可以像其他任何测试一样容易.

This example uses enzyme and snapshot testing but could just as easily be any other test.

这避免了我需要使用<MemoryRouter>作为打字稿不喜欢的包装器.

This avoided me needing to use <MemoryRouter> as a wrapper that typescript did not like anyhow.

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

注意请勿使用它来测试实现细节,这可能很诱人,但是如果您要重构,它会给您带来很多痛苦.

CAUTION Do not use this to test implementation detail, it can be tempting but it will cause you a lot of pain should you want to refactor.

为此提供帮助可能是使它可重复使用的最佳方法.

Making a helper for this would probably be the best way to make this re-usable.

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函数

Now we can just use the routerTestProps function in our tests

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

这篇关于如何使用RouteComponentProps测试React组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆