用酶进行反应测试,无法读取未定义的 属性 'route'
React test with Enzyme, cannot read property 'route' of undefined
在我的 React 应用程序(无 flux / redux)中,我正在尝试使用 enzyme
对组件进行单元测试,浅渲染 效果很好,我能够检索它的状态等,但是 mount rendering 给我一个 cannot read property 'route' of undefined
.
的错误
我的App.js
看起来像这样
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<MyCustomLayout>
<Route path="/mypath" component={myComponent} />
</MyCustomLayout>
</Switch>
</BrowserRouter>
)
}
这是 myComponent
的代码
import React, { Component } from 'react';
import './index.css';
import { getList } from './apiService.js';
class myComponent extends Component {
constructor(props) {
super(props);
this.state = {
myList: [],
};
}
componentDidMount() {
// get list ajax call
getList().then(response => {
this.setState({
myList: response.data
})
});
}
handleClick = () => {
this.props.history.push('/home');
}
renderMyList() {
/*
Code for rendering list of items from myList state
*/
}
render() {
return (
<div>
<h1>Hello World</h1>
<button onClick={this.handleClick}>Click me</button>
{this.renderMyList()}
</div>
)
}
}
export default myComponent
这是我的测试代码
import React from 'react';
import myComponent from './myComponent';
import renderer from 'react-test-renderer';
import { shallow, mount } from 'enzyme';
import sinon from 'sinon';
test('Initial state of myList should be empty array ', () => {
const component = shallow(<myComponent/>);
expect(component.state().myList).toEqual([]);
});
test('Make sure the componentDidMount being called after mount', () => {
sinon.spy(myComponent.prototype, 'componentDidMount');
const component = mount(<myComponent/>);
expect(myComponent.prototype.componentDidMount.calledOnce).toEqual(true);
});
错误是什么?
前几天在这里遇到了这个问题 - 你得到这个错误的原因是因为你试图安装 <Route />
或 <Link />
或用 [=15 包裹的组件=] 当代码周围没有 <Router />
时。这些组件需要特定的上下文(<Router />
提供),因此为了测试这些组件,您必须将组件安装在 <MemoryRouter />
.
中
这是一个为您执行此操作的函数:
const mountWithRouter = Component => mount(
<MemoryRouter>
{Component}
</MemoryRouter>
);
下面是你如何使用它:
test('Make sure the componentDidMount being called after mount', () => {
sinon.spy(myComponent.prototype, 'componentDidMount');
const component = mountWithRouter(<myComponent/>);
expect(myComponent.prototype.componentDidMount.calledOnce).toEqual(true);
});
也就是说,在迁移到 react-router@^4.0.0
时,我最终试图删除大部分已安装的测试代码 - 这很麻烦。这样做的主要缺点是您在此测试中的 const component
不再是 myComponent
,而是 MemoryRouter
。这意味着您不能很容易地深入了解它的状态等。
编辑:
当我确实需要检查我 "had" 要安装的组件的状态时,我所做的一个例子是我浅渲染它,然后 运行 生命周期我手动需要的方法,如下所示:
test('populates state on componentDidMount', () => {
const wrapper = shallow(<MyComponent />);
wrapper.instance().componentDidMount();
expect(wrapper.state()).toBe({ some: 'state' });
});
这样一来,我完全不用处理路由器问题(因为没有挂载),我仍然可以测试我需要测试的东西。
在我的 React 应用程序(无 flux / redux)中,我正在尝试使用 enzyme
对组件进行单元测试,浅渲染 效果很好,我能够检索它的状态等,但是 mount rendering 给我一个 cannot read property 'route' of undefined
.
我的App.js
看起来像这样
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<MyCustomLayout>
<Route path="/mypath" component={myComponent} />
</MyCustomLayout>
</Switch>
</BrowserRouter>
)
}
这是 myComponent
import React, { Component } from 'react';
import './index.css';
import { getList } from './apiService.js';
class myComponent extends Component {
constructor(props) {
super(props);
this.state = {
myList: [],
};
}
componentDidMount() {
// get list ajax call
getList().then(response => {
this.setState({
myList: response.data
})
});
}
handleClick = () => {
this.props.history.push('/home');
}
renderMyList() {
/*
Code for rendering list of items from myList state
*/
}
render() {
return (
<div>
<h1>Hello World</h1>
<button onClick={this.handleClick}>Click me</button>
{this.renderMyList()}
</div>
)
}
}
export default myComponent
这是我的测试代码
import React from 'react';
import myComponent from './myComponent';
import renderer from 'react-test-renderer';
import { shallow, mount } from 'enzyme';
import sinon from 'sinon';
test('Initial state of myList should be empty array ', () => {
const component = shallow(<myComponent/>);
expect(component.state().myList).toEqual([]);
});
test('Make sure the componentDidMount being called after mount', () => {
sinon.spy(myComponent.prototype, 'componentDidMount');
const component = mount(<myComponent/>);
expect(myComponent.prototype.componentDidMount.calledOnce).toEqual(true);
});
错误是什么?
前几天在这里遇到了这个问题 - 你得到这个错误的原因是因为你试图安装 <Route />
或 <Link />
或用 [=15 包裹的组件=] 当代码周围没有 <Router />
时。这些组件需要特定的上下文(<Router />
提供),因此为了测试这些组件,您必须将组件安装在 <MemoryRouter />
.
这是一个为您执行此操作的函数:
const mountWithRouter = Component => mount(
<MemoryRouter>
{Component}
</MemoryRouter>
);
下面是你如何使用它:
test('Make sure the componentDidMount being called after mount', () => {
sinon.spy(myComponent.prototype, 'componentDidMount');
const component = mountWithRouter(<myComponent/>);
expect(myComponent.prototype.componentDidMount.calledOnce).toEqual(true);
});
也就是说,在迁移到 react-router@^4.0.0
时,我最终试图删除大部分已安装的测试代码 - 这很麻烦。这样做的主要缺点是您在此测试中的 const component
不再是 myComponent
,而是 MemoryRouter
。这意味着您不能很容易地深入了解它的状态等。
编辑:
当我确实需要检查我 "had" 要安装的组件的状态时,我所做的一个例子是我浅渲染它,然后 运行 生命周期我手动需要的方法,如下所示:
test('populates state on componentDidMount', () => {
const wrapper = shallow(<MyComponent />);
wrapper.instance().componentDidMount();
expect(wrapper.state()).toBe({ some: 'state' });
});
这样一来,我完全不用处理路由器问题(因为没有挂载),我仍然可以测试我需要测试的东西。