我使用jest
来测试来自react-router v4的<Link>
组件。
我收到警告,<Link />
需要来自react-router <Router />
组件的上下文。
如何在测试中模拟或提供路由器上下文? (基本上我该如何解决此警告?)
Link.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
test('Link matches snapshot', () => {
const component = renderer.create(
<Link to="#" />
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
运行测试时的警告:
Warning: Failed context type: The context `router` is marked
as required in `Link`, but its value is `undefined`.
答案 0 :(得分:25)
您可以使用StaticRouter将组件包装在测试中,以将路由器上下文放入组件中:
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
import { StaticRouter } from 'react-router'
test('Link matches snapshot', () => {
const component = renderer.create(
<StaticRouter location="someLocation" context={context}>
<Link to="#" />
</StaticRouter>
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
查看反应路由器docs about testing
答案 1 :(得分:22)
我遇到了同样的问题,并且使用StaticRouter
仍然需要context
需要更多配置才能在我的测试中使用它,所以我最终使用的MemoryRouter
非常有效好吧,没有任何问题。
import React from 'react';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
// SampleComponent imports Link internally
import SampleComponent from '../SampleComponent';
describe('SampleComponent', () => {
test('should render', () => {
const component = renderer
.create(
<MemoryRouter>
<SampleComponent />
</MemoryRouter>
)
.toJSON();
expect(component).toMatchSnapshot();
});
});
答案 2 :(得分:-1)
我的测试是这样的:
import * as React from 'react'
import DataBaseAccout from '../database-account/database-account.component'
import { mount } from 'enzyme'
import { expect } from 'chai'
import { createStore } from 'redux'
import reducers from '../../../reducer/reducer'
import { MemoryRouter } from 'react-router'
let store = createStore(reducers)
describe('mount database-account', () => {
let wrapper
beforeEach(() => {
wrapper = mount(
< MemoryRouter >
<DataBaseAccout store={store} />
</MemoryRouter >
)
})
afterEach(() => {
wrapper.unmount()
wrapper = null
})
})
答案 3 :(得分:-1)
以上解决方案具有一个常见的默认缺陷:
无法访问您组件的实例!,因为MemoryRouter
或StaticRouter
组件包裹了您的组件。
因此,解决此问题的最佳方法是模拟路由器上下文,代码如下:
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
describe('YourComponent', () => {
test('test component with react router', () => {
// mock react-router context to avoid violation error
const context = {
childContextTypes: {
router: () => void 0,
},
context: {
router: {
history: createMemoryHistory(),
route: {
location: {
hash: '',
pathname: '',
search: '',
state: '',
},
match: { params: {}, isExact: false, path: '', url: '' },
}
}
}
};
// mount component with router context and get component's instance
const wrapper = mount(<YourComponent/>, context);
// access your component as you wish
console.log(wrapper.props(), wrapper.state())
});
beforeAll(() => {
configure({ adapter: new Adapter() });
});
});