我有一项任务是在上层某处测试依赖于BrowserRouter
组件的React组件。据我所知BrowserRouter
将路由对象传递给任何孩子,孙子等的道具。
组件:
import React, { Component } from 'react';
import Program from './Program';
export default class Programs extends Component {
constructor() {
super();
this.state = {
programs: [
/** example */
{ id: 10, name: 'Golden Knights' },
{ id: 20, name: 'Silver Lords' },
{ id: 30, name: 'Wooden Kings' },
],
};
}
render() {
const { programs } = this.state;
return (
<ul className="programs">{/*<-- add class "att-programs"*/}
{
programs.map(
program => <Program
key={program.id}
program_id={program.id}
program_name={program.name}
/>,
)
}
</ul>
);
}
}
当我尝试独立测试此组件时,出现错误:Cannot read property 'route' of undefined
。要解决此问题,我将我的元素包装到MemoryRouter
组件中,我的测试看起来如下:
import React from 'react';
import renderer from 'react-test-renderer';
import { mount, shallow } from 'enzyme';
import { MemoryRouter } from 'react-router-dom';
import Programs from '../../src/components/Programs';
describe('<Programs />', () => {
it('Renders list for any child from state', () => {
const wrapper = mount(<MemoryRouter><Programs /></MemoryRouter>);
const programs = wrapper.find(Programs);
expect(programs.length).toBe(1);
programs.setState({
programs: [
{ id: 1, name: 'qwe' },
{ id: 2, name: 'asd' },
{ id: 3, name: 'zxc' },
],
});
expect(wrapper.find('li').length).toBe(3);
expect(wrapper.find('a[href="/player/1"]').length).toBe(1);
});
});
现在我有另一个问题:ReactWrapper::setState() can only be called on the root
请帮我弄清楚如何模拟路由器但能够在测试组件上定义setState
?
答案 0 :(得分:2)
我建议不要直接更新组件的内部状态。哟是以某种方式操纵该状态的方式(或者你计划)。因此在测试期间使用这些机制。例如。您可能需要考虑通过wrapper.simulate("click")
点击按钮并更改状态。之后,您可以验证状态转换是否正确。