如何使用 react-intl、react-router-dom v4 和 TypeScript 对 React 组件进行单元测试

How To Unit Test React Component With react-intl, react-router-dom v4 and TypeScript

我目前正在尝试对 React Class 组件中的函数进行单元测试。我已经尝试了所有可以访问实际组件的方法。

应用程序当前设置如下:

<IntlProvider ...>
    <BrowserRouter>
        <App/>
    </BrowserRouter>
</IntlProvider>

我想测试的组件,我们称之为用户,在内部定义为:

<Route
    path="/users"
    render={(routeProps) => {
        return (
            <Users
                {...routeProps}
            />
        );
    }}
/>

用户组件是这样的:

type Props = {...}

type State = {...}

class Users extends Component<Props, State> {

    constructor(props: any) { super(props); }

    componentDidMount() { ... }

    componentWillUnmount() { ... }

    isReadOnly = (): boolean => {
        // determine if read only.
    }

}

export default withRouter(Users)

我正在尝试测试一个名为 isReadOnly 的函数。然而,我需要在组件上执行 setState() 才能真正调用该函数。

到目前为止我已经尝试过:

const wrapper = shallow(<OrderEntry {...props}/>);

但它抛出一个错误:ShallowWrapper::setState() can only be called on class components

我想这一定是因为 BrowserRouter。所以我发现我需要用 MemoryRouter 来解决这个问题。

const wrapper = shallow(<MemoryRouter><Users {...props}/></MemoryRouter>);
const usersInstance = wrapper.find(Users).dive().instance();
usersInstance.setState(state);

这会引发错误:TypeError: Cannot read property 'setState' of null

如果我console.log(wrapper),它输出:ShallowWrapper {}

我对此有点迷茫...我只需要能够做两件事 - 设置状态和对组件功能之一进行单元测试。

Redux docs 建议导出未连接的组件(Users 在你的情况下)并在测试中使用它。这样,您就可以完全控制传递给渲染实例的道具,作为奖励,使用酶的 setState.

没有问题

所以像这样:

export class Users extends Component<Props, State> {

    componentDidMount() { ... }

    componentWillUnmount() { ... }

    isReadOnly = (): boolean => {
        // determine if read only.
    }
}
export default withRouter(Users);

并在测试中:

import {Users} from "./Users";